回溯总结篇

提示:努力生活,开心、快乐的一天


回溯法理论基础

回溯是递归的副产品,只要有递归就会有回溯
回溯法就是暴力搜索,并不是什么高效的算法,最多再剪枝一下
回溯法的模板:

function backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}

组合问题

组合问题

for循环横向遍历,递归纵向遍历,回溯不断调整结果集
剪枝精髓是:for循环在寻找起点的时候要有一个范围,如果这个起点到集合终止之间的元素已经不够题目要求的k个元素了,就没有必要搜索了。
在这里插入图片描述

组合总和

组合总和(一)

加了一个元素总和的限制,剪枝操作:已选元素总和如果已经大于n(题中要求的和)了,那么往后遍历就没有意义了,直接剪掉,剪枝的代码可以在for循环加上 i <= 9 - (k - path.size()) + 1 的限制
在这里插入图片描述

组合总和(二)

本题没有数量要求,可以无限重复,但是有总和的限制,所以间接的也是有个数的限制
本题剪枝操作:

for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++)

在这里插入图片描述

组合总和(三)

集合元素会有重复,但要求解集不能包含重复的组合,添加去重逻辑,“树枝去重”和“树层去重”,去重问题先排序
在这里插入图片描述

多个集合求组合

每一个数字代表的是不同集合,也就是求不同集合之间的组合,所以不需要startIndex
在这里插入图片描述

切割问题

切割问题难点:

  • 切割问题其实类似组合问题
  • 如何模拟那些切割线
  • 切割问题中递归如何终止
  • 在递归循环中如何截取子串
  • 如何判断回文
    用求解组合问题的思路来解决 切割问题,后序如何模拟切割线,如何终止,如何截取子串,最后判断回文
    在这里插入图片描述

子集问题

子集问题(一)

在树形结构中子集问题是要收集所有节点的结果,而组合问题是收集叶子节点的结果

result.push_back(path); // 收集子集,要放在终止添加的上面,否则会漏掉结果
if (startIndex >= nums.size()) { // 终止条件可以不加
    return;
}

在这里插入图片描述

子集问题(二)

针对子集问题进行去重,组合中的去重逻辑
在这里插入图片描述

递增子序列

不能先进行排序
在这里插入图片描述

排列问题

排列问题(一)

排列是有序的,也就是说 [1,2] 和 [2,1] 是两个集合,所以处理排列问题就不用使用startIndex了。

  • 每层都是从0开始搜索而不是startIndex
  • 需要used数组记录path里都放了哪些元素了
    在这里插入图片描述

排列问题(二)

又一次强调了“树层去重”和“树枝去重”
这道题目神奇的地方就是used[i - 1] == false(树层去重)也可以,used[i - 1] == true(树枝去重)也可以!
树层上去重(used[i - 1] == false),的树形结构如下:在这里插入图片描述
树枝上去重(used[i - 1] == true)的树型结构如下:
在这里插入图片描述
使用(used[i - 1] == false),即树层去重,效率更高!

去重问题

统一使用used数组来去重的,其实使用set也可以用来去重!
使用used数组去重 和 使用set去重 两种写法的性能差异:

  • 使用set去重的版本相对于used数组的版本效率都要低很多
  • 使用set去重,不仅时间复杂度高了,空间复杂度也高了

性能分析

1、子集问题分析:

  • 时间复杂度:O(2n),因为每一个元素的状态无外乎取与不取,所以时间复杂度为O(2n)
  • 空间复杂度:O(n),递归深度为n,所以系统栈所用空间为O(n),每一层递归所用的空间都是常数级别,注意代码里的result和path都是全局变量,就算是放在参数里,传的也是引用,并不会新申请内存空间,最终空间复杂度为O(n)

2、排列问题分析:

  • 时间复杂度:O(n!),这个可以从排列的树形图中很明显发现,每一层节点为n,第二层每一个分支都延伸了n-1个分支,再往下又是n-2个分支,所以一直到叶子节点一共就是 n * n-1 * n-2 * … 1 = n!。
  • 空间复杂度:O(n),和子集问题同理。

3、组合问题分析:

  • 时间复杂度:O(2^n),组合问题其实就是一种子集的问题,所以组合问题最坏的情况,也不会超过子集问题的时间复杂度。
  • 空间复杂度:O(n),和子集问题同理。

🎈今日心得

今天很忙,所以hard题就没做,周末休息日再看吧,只是复习了一下回溯算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值