参考文献 代码随想录
一、组合
给定两个整数 n
和 k
,返回范围 [1, n]
中所有可能的 k
个数的组合。
你可以按 任何顺序 返回答案。
示例 1:
输入:n = 4, k = 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]
示例 2:
输入:n = 1, k = 1 输出:[[1]]
提示:
1 <= n <= 20
1 <= k <= n
问题分析:回溯主要考虑到参数和处理逻辑
def __init__(self): self.ans = [] self.stack = [] def combine(self, n, k): """ :type n: int :type k: int :rtype: List[List[int]] """ self.backstrking(1, n, k) return self.ans def backstrking(self,start, n, k): if len(self.stack) == k: self.ans.append(self.stack[:]) return for i in range(start, n + 1): self.stack.append(i) self.backstrking(i + 1, n, k) self.stack.pop()
剪枝
class Solution(object): def __init__(self): self.ans = [] self.stack = [] def combine(self, n, k): """ :type n: int :type k: int :rtype: List[List[int]] """ self.backstrking(1, n, k) return self.ans def backstrking(self,start, n, k): if len(self.stack) == k: self.ans.append(self.stack[:]) return for i in range(start, n - (k - len(self.stack)) + 2): # n - (k - len(self.stack)) + 2。(k - len(self.stack)这个试求,还需要多少个元素n - (k - len(self.stack))最多的起始遍历位子(最多遍历到当前这个数,往后遍历,没有满足要求) self.stack.append(i) self.backstrking(i + 1, n, k) self.stack.pop()
二、组合总和 III
找出所有相加之和为 n
的 k
个数的组合,且满足下列条件:
- 只使用数字1到9
- 每个数字 最多使用一次
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
示例 1:
输入: k = 3, n = 7 输出: [[1,2,4]] 解释: 1 + 2 + 4 = 7 没有其他符合的组合了。
示例 2:
输入: k = 3, n = 9 输出: [[1,2,6], [1,3,5], [2,3,4]] 解释: 1 + 2 + 6 = 9 1 + 3 + 5 = 9 2 + 3 + 4 = 9 没有其他符合的组合了。
示例 3:
输入: k = 4, n = 1 输出: [] 解释: 不存在有效的组合。 在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。
class Solution(object): def __init__(self): self.ans = [] self.stack = [] def combinationSum3(self, k, n): """ :type k: int :type n: int :rtype: List[List[int]] """ self.backstrikng(1, k, n) return self.ans def backstrikng(self, startIndex, k, n): if sum(self.stack) == n and len(self.stack) == k: self.ans.append(self.stack[:]) for i in range(startIndex, 10): self.stack.append(i) self.backstrikng(i + 1, k , n) self.stack.pop()
剪枝
class Solution(object): def __init__(self): self.ans = [] self.stack = [] def combinationSum3(self, k, n): """ :type k: int :type n: int :rtype: List[List[int]] """ self.backstrikng(1, k, n) return self.ans def backstrikng(self, startIndex, k, n): if sum(self.stack) > n: # 一旦返现和大于n,那么就结束掉 return if sum(self.stack) == n and len(self.stack) == k: self.ans.append(self.stack[:]) for i in range(startIndex, 9 - (k - len(self.stack)) + 2): # 为什么要加2,为什么首先是加1,为什么要加一呢?因为当k = 2, self.stack.size == 0,那么后面就只能取到8,然后要加1才能取到这样才能组合1到9的组合问题 self.stack.append(i) self.backstrikng(i + 1, k , n) self.stack.pop()
三、电话号码的字母组合
给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入:digits = "23" 输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例 2:
输入:digits = "" 输出:[]
示例 3:
输入:digits = "2" 输出:["a","b","c"]
问题分析:上面2题都是用了startIndex,这个是控制不重复元素,并且是在一个集合里,而本题不一样的是在多个集合求组合问题,然后我们定义一index来记录访问到了那个结合,如果index等于digits的长度,那么说明,已经遍历完全部结合,为什么index 是从0开始呢,因为要遍历digits中的按键,那么结束,为什么要等于长度呢?因为,要遍历完digits,如果不等于它的长度,那么当遍历到最后一个按键是,将退出遍历,那么就不满足题目需要。
class Solution(object): def __init__(self): self.dic = { 1:'', 2:"abc", 3:"def", 4:"ghi", 5:"jkl", 6:"mno", 7:"pqrs", 8:"tuv", 9:"wxyz" } self.ans = [] self.stack = [] def letterCombinations(self, digits): """ :type digits: str :rtype: List[str] """ if not digits: return self.ans self.backstriking(digits, 0) return self.ans def backstriking(self, digits, index): if index == len(digits): self.ans.append("".join(self.stack)) return digit = int(digits[index]) # 获取对应的按键 strd = self.dic[digit] # 获取对应的字符串 多个集合组合问题 for i in range(len(strd)): self.stack.append(strd[i]) self.backstriking(digits, index + 1) self.stack.pop()
简化版本
class Solution(object): def __init__(self): self.dic = { 1:'', 2:"abc", 3:"def", 4:"ghi", 5:"jkl", 6:"mno", 7:"pqrs", 8:"tuv", 9:"wxyz" } self.ans = [] def letterCombinations(self, digits): """ :type digits: str :rtype: List[str] """ if not digits: return self.ans self.backstriking(digits, 0, '') return self.ans def backstriking(self, digits, index, s): if index == len(digits): self.ans.append(s) return digit = int(digits[index]) # 获取对应的按键 strd = self.dic[digit] # 获取对应的字符串 2个集合组合问题 for i in range(len(strd)): self.backstriking(digits, index + 1, s + strd[i])