代码随想录 day27|day28|day29

回溯2

切割问题:是在每个节点判断是否是要剪枝收割元素。 startidx 是切割起点,i是本次切割终点

分割回文串
复原ip地址
非递减子序列
都是在树的节点依照题意判断,之后决定是否剪枝。
也就是都有if判断来剪枝 。
下面是非递减子序列。
在这里插入图片描述
下面是回文串
在这里插入图片描述
下面是复原ip地址
在这里插入图片描述

子集问题: 与组合问题的区别是在每个节点上收割结果 。

子集
子集去重:主要是树层去重。 判断条件是

if(used[i-1] == 0 && i> 0 && nums[i] == nums[i-1] ) 

在这里插入图片描述

[子集2] (https://leetcode.cn/problems/subsets-ii/description/)

组合问题

在每个节点收割元素 。 记住startidx 在每次递归时 要加1 。 这相当于for循环的i++ ;
这种回溯递归就是暴力枚举 。 不过是把代码简化了,并且把问题抽象为树。
组合总和
涉及到去重。 一般是树层元素去重。 树枝不去重。
如果发现重复的元素。直接剪枝(continue掉这次for循环)

 if( i >0   && candidates[i-1] == candidates[i] && 0 ==used[i-1] )
            {
                continue ; 
            }

used[i-1] =0 确保这是在处理同一树层的元素。 因为used[i-1] = 1 的话表示处理的是树枝元素, 是从上一个树枝元素递归过来的元素。

组合总和II

排列问题:与组合问题不同的是,组合是同一个的组合,可能是不同的排列.要使用used数组,表示在本次树枝的遍历使用过的元素,使用过的就不使用了。 另外每次树枝都是从i==0 开始遍历。

全排列

  void backtracking(vector<int>& nums  , int k )
    {
        if(path.size() == k) // 递归边界 
        {
            res.push_back(path) ;
            return  ; 
        }
        if(path.size() > k)
        {
            return ; 
        }
        for(int i = 0  ; i< nums.size(); ++ i)
        {
            if( used[i] == 0 )
            {
            path.push_back(nums[i]) ;
            used[i] = 1 ; 
            backtracking(nums, k ) ; 
            used[i] = 0 ; 
            path.pop_back() ; 
            }
  
        }
    }

全排列去重也和组合去重一样都是把树层的元素 去重,通过剪枝去重

 if(i>0  && nums[i-1] == nums[i] && used[i-1] == 0 )
            {
                continue ; 
            }

[全排列2](https://leetcode.cn/problems/permutations-ii/description/)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值