216.组合总和III
思路
按照回溯算法的逻辑,写代码。
递归函数的参数,除了原有的n, k, startIndex,增加一个sum,计算当前path中的和。
终止条件用sum与n比较,如果满足相等,且满足长度为k,则加入result。
尝试写代码:
class Solution:def __init__(self):self.path = []self.result = []def combinationSum3(self, k: int, n: int) -> List[List[int]]:self.backtracking(k, n, 1, 0)return self.resultdef backtracking(self, k, n, startIndex, sum):if sum == n:if len(self.path) == k:self.result.append(self.path[:])sum = 0returnelif sum > n:returnfor i in range(startIndex, 10):if sum < n:self.path.append(i)sum += iself.backtracking(k, n, i + 1, sum)self.path.pop()sum -= i
成功通过!
但是对于终止条件那里还是有点模糊,不知道为什么两个if要嵌套着,不能and连接。
糊里糊涂的过了
根据代码随想录
终止条件,先判断path长度是否为k,如果不满足,返回;在此条件下,再判断当前的sum是否等于n。
剪枝1:
放在终止条件:如果当前sum比n大,则直接返回
剪枝2:
要求共有k个数,如果后面要取的数不够了,剪枝。
该剪枝放在for循环的条件里,写为9 - (k - path.size) + 1
最终代码
class Solution:def __init__(self):self.path = []self.result = []def combinationSum3(self, k: int, n: int) -> List[List[int]]:self.backtracking(k, n, 1, 0)return self.resultdef backtracking(self, k, n, startIndex, sum):if sum > n:returnif len(self.path) == k:if sum == n:self.result.append(self.path[:])returnfor i in range(startIndex, 9 - (k - len(self.path)) + 2):self.path.append(i)sum += iself.backtracking(k, n, i + 1, sum)self.path.pop()sum -= i
总结
终止条件最基本的是长度是否与题目要求的相等,在此基础上再去判断和是否相等。
这样就不需要在for循环内增加条件,因为只要path的长度到k,都会返回,只不过如果再满足sum=n的话,就将当前的path加入result。
如此的整体结构就会很清晰
17.电话号码的字母组合
思路
有点不知道怎么弄
这里每个数字中都能挑选自己的字母,因此不存在startIndex。
先按照流程,递归函数的终止条件,如果是之前的题,需要判断path的长度,
但是由于7和9中有四个数字,而其他有三个数字,这里的for循环的范围不知道该如何确定
for循环就直接从digits中取数
问题
不知道如何将数组和各自的字母联系起来,可以尝试用字典,但具体不确定怎么写
根据代码随想录
要点:
- 用数组做一个映射,将数组的下标与内容对应
- 用二叉树画图,抽象理解,树的深度取决于输入的数的个数
- 函数参数中有一个index,不同于之前的startIndex,index表示当前递归到了第几个数字。因为之前的题是在一个集合中组合,本题是在两个集合中组合,因此不需要startIndex确定集合中之前遍历过哪些元素
- 终止条件:用index判断是否遍历到了digits.size。然后收获结果,返回。这里不同于之前用path.size。不过我觉得用path.size也可以
- 取出一个数,通过数组映射得到这个数对应的字母
- for循环的范围通过上面得到的数字对应的字母的size决定
- 递归时,index + 1,使得下次递归时,取下一个数
尝试写代码:
class Solution:def __init__(self):self.path = ''self.result = []self.letterMap = ['', # 0'', # 1'abc', # 2'def', # 3'ghi', # 4'jkl', # 5'mno', # 6'pqrs', # 7'tuv', # 8'wxyz' # 9]def letterCombinations(self, digits: str) -> List[str]:self.backtracking(digits, 0)return self.resultdef backtracking(self, digits, index):if len(self.path) == len(digits):self.result.append(self.path)returndigit = int(digits[index])letter = self.letterMap[digit]for i in range(len(letter)):self.path += letter[i]self.backtracking(digits, index + 1)self.path = self.path[:-1]
有的通过,有的不对
如果给的digits为空,应该输出空列表,但是result有一个空引号
根据代码随想录:在给定函数开头加个if判断
最终代码
class Solution:def __init__(self):self.path = ''self.result = []self.letterMap = ['', # 0'', # 1'abc', # 2'def', # 3'ghi', # 4'jkl', # 5'mno', # 6'pqrs', # 7'tuv', # 8'wxyz' # 9]def letterCombinations(self, digits: str) -> List[str]:if len(digits) == 0:return self.resultself.backtracking(digits, 0)return self.resultdef backtracking(self, digits, index):if index == len(digits):self.result.append(self.path)returndigit = int(digits[index])letter = self.letterMap[digit]for i in range(len(letter)):self.path += letter[i]self.backtracking(digits, index + 1)self.path = self.path[:-1]
Python方法
使用切片的方式来删除字符串的最后几个字符:
删除最后两个字符:s = s[:-2]
删除最后一个字符:s = s[:-1]
s[:-1]的意思就是s字符串取从第0个字符至倒数第一个字符的前一个字符,这样就达到了去掉最后一个字符的目的。