刷题笔记之回溯算法①

写过二叉树,对递归算法有一些理解之后再来写回溯算法,其实会简单很多。

回溯算法三步走:

第一步:确定递归参数和返回值(参数根据实际情况确定,返回值大多数为void)

第二步:确定递归停止条件

第三步:确定循环中的逻辑(现在的感觉是用最后一层递归的逻辑来写比较好写)

回溯算法实际上就是在原有递归的基础上又加了一个循环。如果把递归理解为深入的话,那么回溯就是浅出。下面用具体的例子来理解这一算法

1 组合

在这一题中,由于k是输入参数,因此我们很难单纯的用for循环来实现。这里我们考虑循环和递归结合的方法。在这里,用递归来处理k个数,循环用来处理每个数的向后遍历。

以k=2为例,递归的深度为2,第一层递归处理第一个数,第二层递归处理第二个数

第一步:参数:n,k,循环的开始点start。返回值为空

第二步:停止条件:数组中已经存了k个数

第三步:循环逻辑:循环开始点为start,结束条件为<=n。每层循环中先把当前点放进数组中,然后进入递归(strat为当前的start(i)加一),递归return之后把这个数从数组中拿出来。

2 组合优化

这一部分实际上是为了对第一题做优化(删掉一些不必要的过程),这一步也叫剪枝。我们考虑第一题提到的算法,我们设置的循环结束条件为<=n,实际上我们可以发现,当开始节点为n-k+1时,就不可能再有满足题意的数组出现了(长度不够),因此我们可以把循环条件改一下。

回溯算法的本质上是一种暴力循环,优化(或者叫剪枝)的目的是减少暴力循环的次数(但并不能改变时间复杂度!)

3 组合总和

停止条件为两层if。第一层if判断数组长度是否为k,第二层条件判断和是否为n。如果长度为k且和为n,数组加入到结果中并return,如果和不为n,直接return。

循环和第一题基本一致。只不过每次同时操作数组和和

4 电话号码的字母组合

细想之下可以发现,这题和之前的组合没什么区别。循环遍历字符对应数组,递归处理字符串中的每一个字符。其他的部分和组合是完全一样的。

5 组合总和

这个题就想对复杂一点。因为这道题并没有固定每个组合的长度。

我们首先对数组进行排序,然后从第一个元素开始递归。直到数组总和大于或等于target。等于的话加到result中,大于的话直接返回并结束当前循环。

6 组合总和二

本题比上一题多了两个个限制条件:要求每个数字只用一次。并且不能出现重复组合。每个数字只用一次可以在递归的时候改变起始位置来实现。处理不出现重复组合可以先对数组进行排序,排序后每次循环时,如果当前元素等于上一个元素,那么就跳过这次循环。(上一题中数组无重复元素,因此没有这种烦恼需要考虑)

7 分割回文串

这道题就又复杂了一点,但抓住循环和递归的关系的话就还好。

循环处理的横向遍历,递归处理的纵向遍历。横向遍历就是当前处理点一步步后移,纵向遍历是当前节点满足,start节点后移,进行下一个节点的处理。

返回条件是开始节点start ==字符串大小。

8 复原ip地址

这个题和分割回文串实际上很像。将返回条件改成两步判断就行,先判断数组长度是否为4,是的话在判断start位置是否在最后,不是的话返回。

9 子集

有两种思路。一是两个循环。一层循环处理子集长度,一层循环找子集。

二是普通的回溯算法。这里就不再需要停止条件了。每次都把当前的数组放到结果中。这种方法更精妙一点,但我感觉不太好想到,,,

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值