关于回溯算法的套路

基本流程:

 注:for循环是横向遍历N叉树,递归是纵向遍历N叉树

for循环起点是start还是0

在递归过程中,下一层是否可以选择集合里的所有元素

可选范围是(start,len)还是(0,len)

当通过一个集合求组合(或分割或子集),需要start,防止重复;

当通过多个集合求组合(或分割或子集),不需要start,因为各个集合都不同不会相互影响;

如果是排列问题的话,就不需要start,因为每到新的一列都需要重新使用之前使用的元素;

如果有start,什么时候递归时i加1?

看下一层中,当前元素是否可重复使用

下一层的可选范围:(i,len)还是(i+1.len)

当一个集合中每个元素只能使用一次时,i + 1;

当一个集合中每个元素可以重复使用时,不用加1;

小结:

设置for的起点,和递归设置i的原理是一样的,用于决定下一层的可选范围

不同的是,如果for设置的起点为0,说明下一层的可选范围是整个集合

递归中i不加1,说明下一层的可选范围是从i(包括i)开始(i可重复使用)

关于去重:

树层(同一层)去重:(当集合中有重复的元素,但是结果要求不能有重复的组合,则需要去重)

有两种方法:如果需要保存原集合的顺序,则采用方法一,如果不需要考虑顺序,采用方法二

方法一:used[i] == false,说明同一树层元素 i 使用过

例题:力扣491. 递增子序列(JavaScript)_csD_Dscnnnnnnn的博客-CSDN博客

491.递增子序列 :给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2。

示例:

  • 输入: [4, 6, 7, 7]
  • 输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]

集合中有重复的元素(两个7),但是结果数组中,不允许有相同的组合,所以需要去重

查找递增序列,必然是不可以打乱集合的排序,所以采用方法一去重

use的下标是nums[i]的值

use初始化的位置:记录同层的元素是否使用过(不涉及递归),所以在进入每层的遍历前,就需要初始化

方法二:排序去重

例题:力扣90. 子集 II(JavaScript)_csD_Dscnnnnnnn的博客-CSDN博客

90.子集II :给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

示例:

  • 输入: [1,2,2]
  • 输出: [ [2], [1], [1,2,2], [2,2], [1,2], [] ]

排序:

nums.sort((a,b)=>a-b)

如果当前元素,与前一个元素相等,则结束此次循环

 for(let i=index;i<len;i++){
            if(i>index&&nums[i]==nums[i-1]){
                continue
            }
            p.push(nums[i])
            dd(i+1)
            p.pop()
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值