刷题总结——回溯算法

总论

  • 增量构造答案
  • 关注边界条件的逻辑
    • 当前操作?(选/不选,枚举选哪一个)
    • 子问题?
    • 下一个子问题?
  • 用什么数据结构保存搜索路径?
  • 时间复杂度计算:搜索树节点数*生成答案需要的时间

题目分类

可以分成子集型、排列型和组合型三种:

回溯问题 时间复杂度O() 解法
子集 LC78 n x 2^n 记录下标i+1
子集 II(有重复) LC90 n x 2^n 同上+hash
排列 面试题08.07 n x n! Vis数组管理或者swap下标
排列II(有重复) 面试题08.08 n x n! 同上+hash
组合型 括号生成LC22 C(2n,n) 剪枝+叶子节点push
  • 使用hash可以理解为一种剪枝方式,主要是去掉重复元素
  • 组合型需要对普通回溯结果根据预设条件进行剪枝

子集型

从执行和答案两个角度考虑问题:

  • 选与不选是从叶子节点的角度考虑,在叶子节点再push答案
  • 枚举选哪个是从回溯过程的角度考虑,需要考虑下标管理,从更大的下标中构造子集

注意使用位运算的迭代思路:不回溯,直接使用2^n位运算计算出上限,然后for循环变量作为mask依次处理

组合型

  • 从n个数字中选择k个数的组合,可以认为是寻找路径长度固定为k的子集
  • 有额外剪枝的可能性,因为选择有顺序(组合保证了顺序的存在,顺序起到了去重的效果)
    • 组合: 每次选的范围缩小,都在0, i-1内,人为规定的逆序
    • 括号生成:状态改变时候的性质
  • 时间复杂度=路径长度X叶子个数,即k X C(n, k)

排列型

可以重复,但顺序不同,因此需要有一个结构存储接下来还能保存哪些数:

  • path:记录搜索路径
  • 集合s:hash记录未选的数字/布尔数组

全排列O(n*n!): 节点路径长度x叶子节点个数

注意全排列可以使用交换法实现,比较巧妙的处理

参考

  1. https://www.bilibili.com/video/BV1xG4y1F7nC/?vd_source=c80c62eac86a4ba033ab112349bbdd9f
  2. https://www.bilibili.com/video/BV1mG4y1A7Gu/?vd_source=c80c62eac86a4ba033ab112349bbdd9f&spm_id_from=333.788.videopod.sections
  3. https://leetcode.cn/problems/permutation-i-lcci/solutions/406850/quan-pai-lie-jiao-huan-fa-qing-xi-tu-shi-by-chen-k/?envType=problem-list-v2&envId=xb9lfcwi
posted @ 2024-10-26 19:02  haydenhs  阅读(28)  评论(0编辑  收藏  举报