今日任务:
资料来源
回溯法,也叫回溯搜索法,是一种用于搜索符合条件的情况的使用递归的通用算法思路。它的本质就是暴力搜索,因此它的效率并不高,但是有些问题是本来就没有什么有效的算法,能出结果就算成功,回溯属于是矬子里拔大个,能提升它的效率的方法只有进行适当的剪枝操作。回溯算法能解决的问题如下:
提示
组合问题和排列问题的区别在于,组合问题的答案不关注元素的顺序,排列问题的答案关注元素的顺序。同为[1, 2],[2, 1],组合问题认为这就是一个答案,排列问题认为这是两种答案。
因为回溯问题都是用递归来解决的,所有所有回溯问题都可以被抽象为树形结构,要查找的集合的大小就构成了树的宽度,递归的深度就构成了树的深度。有递归就要有终止条件,所以这棵树必然是一棵高度有限的n叉树。
相比递归问题的三要素,回溯问题的模板就多了一个回溯的过程:
void backtracking(参数) { if (终止条件) { 存放结果; return; } for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) { 处理节点; backtracking(路径,选择列表); // 递归 回溯,撤销处理结果 } }
题目
给定两个整数 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]]
提示:
这道题就是经典的暴力行不通只能回溯的情况。如果是要暴力循环去做的话,for循环的层数必须要与k相同,这就不可能行得通。而回溯可以通过在递归中进行循环的方式来做。
pythonfrom typing import List
class Solution:
def __init__(self):
self.path = []
self.result = []
def combine(self, n: int, k: int) -> List[List[int]]:
self.back_tracking(n, k, 1)
return self.result
def back_tracking(self, n: int, k: int, start_index: int):
if len(self.path) == k: # 满足条件 终止递归
self.result.append(self.path.copy())
return
for i in range(start_index, n + 1): # 单层递归的逻辑
self.path.append(i)
self.back_tracking(n, k, i + 1)
self.path.pop()
return
这道题也可以进行适当的剪枝操作。一种情况是k为1的时候,那就没什么必要再去递归了,直接生成结果就行了。另外还有k足够大的时候,有些递归的情况里,递归到最后result都不够长,因此注定不会有结果。这部分也可以进行剪枝。剪枝后的代码如下:
pythonfrom typing import List
class Solution:
def __init__(self):
self.path = []
self.result = []
def combine(self, n: int, k: int) -> List[List[int]]:
if k == 1:
return [[i] for i in list(range(1, n + 1))]
self.back_tracking(n, k, 1)
return self.result
def back_tracking(self, n: int, k: int, start_index: int):
if len(self.path) == k: # 满足条件 终止递归
self.result.append(self.path.copy())
return
for i in range(start_index, (n + 1) - (k - len(self.path)) + 1): # 剪枝操作
self.path.append(i)
self.back_tracking(n, k, i + 1)
self.path.pop()
return
剪枝思路:
len(self.path)
个。k - len(self.path)
个。(n + 1) - (k - len(self.path)) + 1)
,如果超过这个终点在继续遍历下去,之后递归到底时的path都不会够k个元素。本文作者:御坂19327号
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!