文档讲解:代码随想录
视频讲解:代码随想录B站账号
状态:看了视频题解和文章解析后做出来了
216.组合总和III
class Solution:
def backtracking(self, k, n, path, result, startindex):
if sum(path) > n:
return
if len(path) == k:
if sum(path) == n:
result.append(path[:])
return
for i in range(startindex, 9 - (k - len(path)) + 2):
path.append(i)
self.backtracking(k, n, path, result, i+1)
path.pop()
return result
def combinationSum3(self, k: int, n: int) -> List[List[int]]:
res = self.backtracking(k, n, [], [], 1)
return res
思路:这题和昨天的组合题非常类似,所以没看题解自己就做出来了。
回溯三部曲:
第一步:确定函数参数。k和n是题目的input必须要传入,path为当前的组合状态,用于终止条件的判断上,result是最后返回的结果集,startindex确保了每个元素只使用一遍且不会有重复的组合出现。
第二步:确定终止条件。当path的长度等于k的时候终止,这里还需加一个if判断,如果path的总和等于k才把path加入到result结果集中,不然直接return。
第三步:确定单层递归逻辑。同样是先在path中append当前遍历的元素,然后backtracking使得startindex+1,最后pop进行回溯。
- 剪枝1:如果path的总和已经大于目标n,直接返回。
- 剪枝2:for循环的终止元素的长度必须大于等于k-len(path)。
剪枝详情如下图:
时间复杂度: O(n * 2^n)
空间复杂度: O(n)
17.电话号码的字母组合
class Solution:
def backtracking(self, digits, path, result, mapping, startindex1):
if len(path) == len(digits):
result.append(''.join(path[:]))
for i in range(startindex1, len(digits)):
for j in range(len(mapping[digits[i]])):
path.append(mapping[digits[i]][j])
self.backtracking(digits, path, result, mapping, i+1)
path.pop()
return result
def letterCombinations(self, digits: str) -> List[str]:
if digits == '':
return []
mapping = {
'0':"", # 0
'1':"", # 1
'2':"abc", # 2
'3':"def", # 3
'4':"ghi", # 4
'5':"jkl", # 5
'6':"mno", # 6
'7':"pqrs", # 7
'8':"tuv", # 8
'9':"wxyz" # 9
}
res = self.backtracking(digits, [], [], mapping, 0)
return res
思路:又是一道独立完成的题目,难道我很适合回溯?
1. 确定函数参数:digits为题目input,path和result哼哈二人组,mapping用于将数字转化为对应的字母,startindex保证无重复。
2. 确定终止条件:当path的长度等digits的长度,终止并append入结果集。
3. 确定单层递归逻辑:两个for循环,第一个循环从startindex开始遍历到digits长度,确保每个元素都被遍历到。第二个for循环遍历当前元素对应的字母表,所以range为len(mapping[digits[i]]). 这里不可以hardcoding为3,因为不同数字对应的字符串长度不同。
时间复杂度: O(3^m * 4^n),其中 m 是对应四个字母的数字个数,n 是对应三个字母的数字个数
空间复杂度: O(3^m * 4^n)