回溯算法总结

本文深入探讨了回溯法的概念及其在组合、排列、切割、子集和棋盘问题中的应用。通过解题模板和实例,解析了回溯法的搜索过程、终止条件以及如何处理去重问题。同时,提到了回溯法在解决旅行路线安排等其他问题上的有效性,并总结了解题中何时使用startIndex、如何进行去重以及二维递归的理解。
摘要由CSDN通过智能技术生成

回溯法

回溯法:暴力解法,遍历问题的所有方案不行就返回。即遍历+递归。

常见的问题:

  • 组合问题:N个数里面按一定规则找出k个数的集合。
  • 排列问题:N个数按照一定规则全排列
  • 切割问题:一个字符串按照一定规则有几种切割方式
  • 子集问题:一个N个数的集合里有多少符合条件的子集
  • 棋盘问题:N皇后,数独问题。

解题模板

可以讲回溯的题目抽象为树形结构,便于理解

void backtracking(参数){
 	if(终止条件)
 	{
 		存放结果;
 		return;
 	}
 	for(选择:本层集合中元素)
 	{
 		处理节点;
 		backtracking(参数,选择列表);//递归
 		撤销处理//回溯
 	}
}
  • 组合问题
    从一组数中选择满足条件的k个数。

  • Leetcode 77.组合(baseline)

  • Leetcode 39.组合总和(media)
    在无重复数组中找出一组数,使其结果为target.数组中每个数可以重复使用!!!

  • Leetcode 40.组合总和||(hard)
    给定一个数组(可能含有重复数),找出一组数,其和为target.涉及去重问题!!!

  • Leetcode 703.组合总和|||(easy)
    给定一个数包含(1-k,不重复),找出和为target的一组数,每个数不可重复使用!!!

  • 多个集合求组合
    Leetcode 17.电话号码的字母组合
    解组合问题,其搜索过程是for循环横向遍历(每个解集),递归纵向遍历(每个解集包含的答案)。
    剪枝问题:在求解过程,很多答案是没必要搜索的,可根据题目的条件添加一些限制项,避免不必要的遍历。可以画树形结构图细化问题。
    组合问题常涉及startIndex即开始坐标,例如,Leetcode 40,703,77,在树形结构中表示下一个开始搜索的下标,以避免出现解集重复问题。
    但也有例外,如Leetcode39中,每个数可以重复使用,这样循环从0开始。
    去重问题:给定数组中存在重复数时,就涉及去重问题,即使同一解集中可以存在重复的数例如[1,3,2,3].但是不同解集中不能有相同答案。例如解集A为[1,2,3,2],解集B为[1,3,2,2].在解集去重问题时,应该先对数组进行排列,然后定义一个数组来标记每个元素是否使用过。
    组合问题的终止条件:题目要求的,例如当数组的个数为k时,或者数组中的和为target时返回。

  • 切割问题
    把给定的字符串划分为子集,按一定规则重新组合起来

    • Leetcode 131.分割回文串
      如何分割将字符串分为不同的子串(回溯)
      然后按题目要求判断合法性
    • Leetcode 0093.恢复IP地址
  • 子集问题
    给定一个数组,求其所有子集。

    • Leetcode 78 子集
    • Leetcode 0090 .子集||—数组存在重复元素,要去重
    • Leetcode 491.递增子序列
      求递增子序列与子集问题相似,都是求子节点。但是数组存在重复数,不能像leetcode 90中直接排序后,用数组标记是否使用过去重,因为这样会打乱顺序。
      组合和分割问题都是求树的叶子节点,而子集问题是找树的所有节点。
      终止条件不同
  • 排列问题
    求给定数组的有多少中排列方式,排列是有序的,也就是说[1,2]和[2,1]是两种排列方式。但是排列涉及到去重问题,避免在同一解集中,把已经得到的答案再次加入。
    即使用数组标记数组中每个数,使得在一次排列中里面的一个元素只能用一次。

    • Leetcode 0046全排列
    • Leetcode 0047 全排列||(数组中含有重复的数)
      排列问题的循环一般是重0开始,而不是startIndex开始
      排列问题一般都涉及标记数组,去重
  • 棋盘问题
    用树的方式,表示棋盘问题

    • Leetcode 51.N皇后问题
    • Leetcode 37 解数独
      将棋盘按行循环
      判断每个位置的合法性
  • 其他问题

    • Leetcode 332.重新安排行程
      利用哈希表实现回溯

总结

1,如何理解回溯法的搜索过程?

回溯的过程可以理解为for循环+递归,循环每一个解集,递归求出这个解集的答案

2,什么时候用startIndex,什么时候不用?

允许答案中有重复元素的不使用startIndex,每次循环从0开始。例如 组合问题(39),排列问题

 反之,在子集,组合77等问题要求解集中不含有重复元素时要使用startIndex标记每次循环开始位置。

3,如何去重?怎么去重?

当数组中存在重复元素,或者对排序有要求时就要考虑去重。当然去重还要考虑不同子集间去重,子集内不同元素去重,还是两者都存在。

常见的方式:数组标记,哈希表

4.如何理解二维递归?

可以把去重问题理解为二维递归

参考:

Leetcode-master

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值