Hello算法笔记之回溯

一、回溯算法介绍:一种通过穷举来解决问题的方法,它的核心思想是从一个初始状态出发,暴力搜索所有可能的解决方案,当遇到正确的解则将其记录,直到找到解或者尝试了所有可能的选择都无法找到解为止。

通常采用「深度优先搜索」来遍历解空间(DFS)。在二叉树章节中提到的前序、中序和后序遍历都属于深度优先搜索。

例题一:给定一个二叉树,搜索并记录所有值为 7 的节点,返回节点列表。

 例题二:在二叉树中搜索所有值为 7 的节点,返回根节点到这些节点的路径

 当走过左下角的节点之后,就会从路径中删掉左下角这个点,并且回到左下角的父节点,进行root.right的遍历,以此类推

复杂的回溯问题还可以加一些约束条件,如例题三:在二叉树中搜索所有值为 7 的节点,返回根节点到这些节点的路径,路径中不能包含值为 3 的节点

当遇到node.val为3时,提前终止搜索 

回溯算法框架代码:

record_solution是更新res

make_choice是更新state

 用此框架解问题三:

 

二、回溯算法的应用

1.全排列问题:在给定一个集合(如一个数组或字符串)的情况下,找出这个集合中元素的所有可能的排列。

①给定的数组中无重复元素的情况:

从回溯算法代码的角度看,候选集合 choices 是输入数组中的所有元素,状态 state 是直至目前已被选择的元素。注意,每个元素只允许被选择一次,因此在遍历选择时,应当排除已经选择过的元素

 ②给定的数组中可能包含重复元素,返回所有不重复的排列

 注意duplicated没有传到backtrack中哦。每轮 backtrack 都包含一个 duplicated 。

 

 假设元素两两之间互不相同,则 n 个元素共有 n! 种排列(阶乘);在记录结果时,需要复制长度为 n 的列表,使用 O(n) 时间。因此,时间复杂度为 O(n!n) 。

空间复杂度:①是O(n) ②是O(n^2)(因为同一时间可能有n个backtrack中的不同duplicated)

2.子集和问题

①给定一个正整数数组 nums 和一个目标正整数 target ,请找出所有可能的组合,使得组合中的元素和等于 target 。给定数组无重复元素,每个元素可以被选取多次。请以列表形式返回这些组合,列表中不应包含重复组合。

 但这里面可能会有重复的子集,比如{4,5}和{5,4}在这里就被算作了两种子集,所以需要剪枝

 ②给定数组可能包含重复元素,每个元素只可被选择一次。列表中不应包含重复组合和重复元素。

 不允许重复选择元素,所以这里backtrack(state, target - choices[i], choices, i + 1, res)中传回去的不是i而是i+1

 

3.N皇后问题:根据国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。给定 n 个皇后和一个 N×N 大小的棋盘,寻找使得所有皇后之间无法相互攻击的摆放方案。比如:

 本题共有三个约束条件:多个皇后不能在同一行、同一列和同一对角线(对角线有两条哦)

1.逐行放置(剪枝1)

2. 用一个长度为 n的布尔型数组 cols 记录每一列是否有皇后。在每次决定放置前,我们通过 cols 将已有皇后的列剪枝,并在回溯中动态更新 cols 的状态。(剪枝2)

3.若两个格子满足 row1 - col1 == row2 - col2 ,则这两个格子一定处在一条主对角线上。 若row1 + col1 == row2 + col2,则这两个格子一定处在一条次对角线上。(剪枝3)

 

diag1 = row - col + n -1 是因为row - col 最小等于1-n 

时间复杂度O(n!)空间复杂度O(n^2)(state使用O(n^2)的空间)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值