Day25 力扣回溯 : 回溯总结| 332.重新安排行程|51. N皇后|37. 解数独
详细布置
今天这三道题都非常难,那么这么难的题,为啥一天做三道?
因为 一刷 也不求大家能把这么难的问题解决,所以
大家一刷的时候,就了解一下题目的要求,了解一下解题思路,不求能直接写出代码,先大概熟悉一下这些题,二刷的时候,随着对回溯算法的深入理解,再去解决如下三题。大家今天的任务,其实是 对回溯算法章节做一个总结就行。
重点是看 回溯算法总结篇:
https://programmercarl.com/%E5%9B%9E%E6%BA%AF%E6%80%BB%E7%BB%93.html
332.重新安排行程(可跳过)
https://programmercarl.com/0332.%E9%87%8D%E6%96%B0%E5%AE%89%E6%8E%92%E8%A1%8C%E7%A8%8B.html
51. N皇后(可跳过)
https://programmercarl.com/0051.N%E7%9A%87%E5%90%8E.html
视频讲解:https://www.bilibili.com/video/BV1Rd4y1c7Bq
37. 解数独(可跳过)
https://programmercarl.com/0037.%E8%A7%A3%E6%95%B0%E7%8B%AC.html
视频讲解:https://www.bilibili.com/video/BV1TW4y1471V
总结
https://programmercarl.com/%E5%9B%9E%E6%BA%AF%E6%80%BB%E7%BB%93.html
我总结:
- 回溯是暴力的,不是高效算法。
- 回溯和递归一起出现,有递归就有回溯。
- 回溯解决组合、分割、子集、排列和上面三个难题(棋盘问题)的问题。
- 回溯有模板,全局变量(全局变量+参数)参与回溯,像hashset不参与。
- 组合问题有startIndex;排列问题每次都从头来;分割问题难在处理字符串和i + 2这样的细节;子集问题就是每个节点都收集结果的分割问题,子集问题因为遍历整个树,也没有什么终止条件。
题解的补充:
1. 组合问题
for循环横向遍历,递归纵向遍历,每一个节点都是一个for循环。
回溯不停的上下动来动去。
组合问题的剪枝精髓是:for循环在寻找起点的时候要有一个范围,如果这个起点到集合终止之间的元素已经不够题目要求的k个元素了,就没有必要搜索了。
用startIndex在一个集合内标记下一次从哪开始,来避免重复。
如果是两个集合的组合问题,就不用startIndex了。根据题目看用不用index来标记做到哪了这样子。
startIndex也是能去重的,但记得要对数组排序!!!
其他问题
懒得写了,代码随想录里写的都挺好的,直接看看吧。我觉得我自己总结的也挺好哈哈哈
回溯模板:
void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择列表); // 递归
回溯,撤销处理结果
}
}