回溯算法开篇:理论及概览
- 回溯函数就是递归函数
- 递归函数下面就包含回溯
- 回溯搜索法,纯暴力搜索——有些结果能暴力搜索出来就很不错了
- 为什么要学习回溯?能解决哪些问题?
- 组合问题【无顺序】——排列组合
- 切割问题:给一个字符串,问如何切割?
- 子集问题——类似组合
- 排列问题【强调顺序】
- 棋盘问题
- 如:N皇后题目
- 题目概览:
- 如何理解回溯法?
- 可以抽象为树形结构——N叉树
- 模板
- 没有返回值——通用命名:backtracking
- 终止条件:收集结果——return
- 单层搜索逻辑:
- for循环(放集合的元素集:每一个元素)
- 处理节点
- 递归函数
- 回溯操作:撤销处理节点的操作——why?——为了得到新的结果
77.组合
题目:
给定两个整数 n
和 k
,返回范围 [1, n]
中所有可能的 k
个数的组合。
你可以按 任何顺序 返回答案。
思路:
第一次做肯定是没有思路的。跟着视频和参考的代码看下来,还是递归三部曲,重要的是参数变多了,需要分清楚各自的作用。
path:第一层
result:接受最终结果
startIndex:第一层里包含的起始数
n:一共有多少个数
k:组合包含的元素的个数
代码:
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]: # 参数和返回值
result = [] # 接收最终结果
self.backtracking(n, k, 1, [], result)
return result
def backtracking(self, n, k, startIndex, path, result): # path 一维数组 result 二维数组 包含的参数
# 确定终止条件:到叶子节点
if len(path) == k:
result.append(path[:]) # 重要!对path进行切片,生成新的数组,避免后面回溯对其产生影响。
return result
# 遍历
for i in range(startIndex, n + 1):
path.append(i)
self.backtracking(n, k, i + 1, path, result)
path.pop() # 回溯!很重要,弹出后再返回上层,继续找新的组合