题目 216.组合总和III
问题描述
找出所有相加之和为n的k个数的组合。组合中只允许含有1-9的正整数,并且每种组合中不存在重复的数字
说明:
所有数字都是正整数。
解集不能包含重复的组合。
解题思路
本题是从1到9里面选k个数,然后和为n。
所以本题涉及到两个减枝操作:
- 像上道题一样要凑够k个数,本题的n就是9了
- 当前和大于目标和减,在回溯之前能操作
代码
class Solution:
def combinationSum3(self, k: int, n: int) -> List[List[int]]:
result = [] # 存放结果集
self.backtracking(n, k, 0, 1, [], result)
return result
def backtracking(self, targetSum, k, currentSum, startIndex, path, result):
if currentSum > targetSum: # 剪枝操作
return # 如果当前和已经超过目标和,直接返回
if len(path) == k:
if currentSum == targetSum:
result.append(path[:])
return
for i in range(startIndex, 10): # 从startIndex到9遍历数字
currentSum += i # 选择数字
path.append(i) # 添加到组合中
self.backtracking(targetSum, k, currentSum, i + 1, path, result) # 递归调用,更新currentSum和startIndex
currentSum -= i # 回溯
path.pop() # 回溯中移除数字
复杂度分析
-
时间复杂度O(k * C(9, k))
在9个数字中选择k个,因此有C(9, k)种可能的组合。对于每个组合,我们需要复制一份加入到结果中,所以总的时间复杂度是O(k * C(9, k))。
-
O(k + C(9, k))
输出结果的存储空间:与上述类似,输出结果的存储空间为O(C(9, k)),因为这是从9个元素中选择k个元素的组合数。
递归栈的空间:递归的深度最多是k,所以递归栈需要的空间是O(k)。
其他空间:包括path和一些变量i的空间,但是这些都可以忽略不计,因为它们的大小是固定的。
题目 17.电话号码的字母组合
重做的代码问题
self.s的初始值应该是"“,而不是” "。
在递归函数backtracking中,每次调用时,你需要递增索引值index,以便处理数字字符串中的下一个数字。
在Python中,要删除字符串的最后一个字符,可以使用self.s = self.s[:-1]。
for i in “abc”: i=a/b/c
问题描述
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:“23”
输出:[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].
解题思路
-
本题其实就是一个排列组合,按下“23”两个键,就会出现9种情况的字母组合。
-
这个问题可以化成二叉树吗,比如:
-
把每个数字代表的字母组合想象成一个长度为3或者4的string,可以按顺序创建一个列表或者字典,为了代码更加精简采用列表。
-
定义代码结构
-
- 首先定义一个init函数,把字母列表,可能的组合s,结果result,作为全局变量定义好。
-
- 定义backTracking回溯函数,进行回溯操作,需要输入的digits和index作为函数,index是digits函数的索引,就是索引当前digits对应的digit。
-
- backTracking中,终止条件:就是len(digits)==index的时候,result记录s,可能会觉得index索引怎么可能和长度相同,s每添加一个字母,index都要加1,当加完的时候,index=2,此时再一次调用回溯函数,已经停止了。
-
- backTracking中,回溯逻辑:先把digits中对应的digit转化为int形,获取对应的字母集,然后进行第一个for循环,s添加第一个字母,index加一,再对下一个digit对应的字母集进行递归。然后进行回溯操作,返回到第二个循环。
代码
class Solution:
def __init__(self):
self.case={
0:"",
1:"",
2:"abc",
3:"def",
4:"ghi",
5:"jkl",
6:"mno",
7:"pqrs",
8:"tuv",
9:"wxyz"
}
self.s=""
self.res=[]
def backtracking(self, digits, index):
#index is the len of the s, s must euqls to the digita as result
#end
if len(digits)==index:
self.res.append(self.s)
return
#single layer
#因为数字不同,所以每次循环的长度不同,设置一个index保存当前记录的数字下标
for j in self.case[int(digits[index])]:
self.s+=j
self.backtracking(digits,index+1)
#易错点
self.s=self.s[:-1]
#backtracking
def letterCombinations(self, digits):
if digits=="":
return []
self.backtracking(digits,0)
return self.res