216. 组合总和III
题目链接:216. 组合总和 III - 力扣(LeetCode)
思路和上一次的组合(LeetCode77. 组合)思路差不多,只不过在判断条件是当所得数组的长度为k时,直接返回,如果和为n时,把组合加入结果集。
class Solution(object):
def backtracking(self, k, n, startIdx, path, result):
if len(path) == k and sum(path[:]) == n:
result.append(path[:])
if len(path) == k:
return
for i in range(startIdx, 9 - (k-len(path))+2):
path.append(i)
self.backtracking(k, n, i+1, path, result)
path.pop()
def combinationSum3(self, k, n):
result = []
path = []
startIdx = 1
self.backtracking(k, n, startIdx, path, result)
return result
而在代码随想录中,在添加数字到组合中时,就刷新了组合的和,回溯时不仅把path添加的元素弹出,也要把刚才加的元素减去,这个做法更能展现【回溯】的思想——把递归操作都撤回。另外,代码海提供了剪枝思路:当组合中的元素继续被添加,且已有和大于所要求的和时,就直接返回,不继续添加元素了,因为之后的和只会更大。注意这里能剪枝的原因是我们的集合是1到9的正数,如果有负数,就不能直接这样剪枝。
17. 电话号码的字母总和
题目链接:17. 电话号码的字母组合 - 力扣(LeetCode)
思路
解这道题,关键在于构建好回溯的树形结构,树形结构的每一条纵向枝蔓代表一个答案,每一层代表从一个集合中获取元素,当获取玩这层的元素后,就进行递归,再回溯。
代码实现
class Solution(object):
def __init__(self):
self.letterMap = [
"", # 0
"", # 1
"abc", # 2
"def", # 3
"ghi", # 4
"jkl", # 5
"mno", # 6
"pqrs", # 7
"tuv", # 8
"wxyz" # 9
]
self.result = []
self.s = ""
def backtracking(self, digits, index):
if index == len(digits):
self.result.append(self.s)
return
digit = int(digits[index]) # 将索引处的数字转换为整数
letters = self.letterMap[digit] # 获取对应的字符集
for i in range(len(letters)):
self.s += letters[i]
index += 1
self.backtracking(digits, index)
self.s = self.s[:-1] # 回溯
index -=1
def letterCombinations(self, digits):
if len(digits) == 0:
return self.result
self.backtracking(digits, 0)
return self.result