回溯基本理论
重要知识点:文章讲解
1)回溯本质是枚举
2)解决的问题:排列组合、棋盘问题等
3)模板
void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择列表); // 递归
回溯,撤销处理结果
}
}
对应有限高度的n叉树
组合
1.题目
给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。你可以按 任何顺序 返回答案。
2.实现
思路:
1)首先按照什么顺序把什么元素添加进来——决定for循环结构和第一层for循环
2)for循环后处理节点,并递归——决定第二层for循环(基于第一层的基础上)
3)记得回溯!
class Solution:
def __init__(self):
self.res = []
def combine2(self, tmp, s, n, k):
if len(tmp) == k:
self.res.append(tmp[:])
return
for i in range(s, n+1):
if n + 1 - i < k - len(tmp): # 集合中元素不够
return
tmp.append(i)
self.combine2(tmp, i + 1, n, k)
tmp.pop()
def combine(self, n: int, k: int) -> List[List[int]]:
tmp = []
self.combine2(tmp, 1, n, k)
return self.res
拓展题目: 216.组合总和III
剪枝优化目前还算简单,但写完之后一定要想这个问题
17.电话号码的字母组合
1.题目
2.实现
只要想清楚每层for循环是什么就行
class Solution:
def __init__(self):
self.res = []
def lettercombine(self, ss, tmp, i):
if i == len(ss):
self.res.append(tmp)
return
t = ss[i]
if t == '2':
l = "abc"
elif t == '3':
l = "def"
elif t == '4':
l = "ghi"
elif t == '5':
l = "jkl"
elif t == '6':
l = "mno"
elif t == '7':
l = "pqrs"
elif t == '8':
l = "tuv"
elif t == '9':
l = "wxyz"
else:
return # 这里考虑到除2-9之外的无用按键都应该返回!!!
for u in l: # 建议放在字典里,值为字符串即可
self.lettercombine(ss, tmp + u, i + 1)
def letterCombinations(self, digits: str) -> List[str]:
if len(digits) == 0:
return self.res
self.lettercombine(digits, "", 0)
return self.res