回溯法总结题型——组合排列、子集、分割

本文介绍了如何使用回溯法解决组合、子集、分割和排列问题。组合问题关注选取k个数的流程,并在有重复元素时去除重复。子集问题寻找所有可能的子集,包括空集。切割问题中,每次切割后继续在剩余部分切割。排列问题允许元素在不同层级出现,通过used数组避免重复。同时讨论了八皇后问题的回溯解决方案。
摘要由CSDN通过智能技术生成

注:图片借鉴代码随想录

组合问题

回溯法解决组合问题的最基础题型
在这里插入图片描述
我们把这个选k个数的流程用树来画出来:
在这里插入图片描述
我们可以看到,组合问题的特点就是对于1来说,取过1的分支已经在走了,则其他分支不需要考虑1了(和排列不同,排列的话在不同层的1是不一样的情况)。我们递归遍历时,下一层都从上一层的id+1开始取数。

    void backtrack(int k,int n, int nowid, vector<vector<int>>& res, vector<int>& temp){
   
        if(temp.size()==k){
   
            res.push_back(temp);
            return;
        }
        for(int i=nowid;i<=n;i++){
     //相当于树中同层遍历
            temp.push_back(i);
            backtrack(k,n,i+1,res,temp); //向下递归
            temp.pop_back();
        }
    }

组合问题2:当数组中有重复元素的时候,求所有组合情况的时候如何去重?
在这里插入图片描述
首先理解一下重复是怎么造成的 [10,1a,1b]
在这里插入图片描述

  • 取1a–>不取1b
  • 取1b
    这两者是一样的
    在dfs过程中,dfs(1a往后)一定cover了dfs(1b往后)的可能性,所以没有必要放1b.

我们要区分往下递归和横向遍历,
对于往下递归来说,可以有重复的1,它代表结果数组中可以出现重复的数如1,1,2 ,
对于横向遍历来说,虽然有1a和1b这两个1,但它们本质是一样的,同层放入同样数就是组合的重复,我们需要跳过这种情况。
注意:有同样数的情况,我们需要先排序,这样方便跳过。

    void backtrack(vector<vector<int>>& res, vector<int>& temp,
    vector<int>& candidates,int target,int nowSum,int id){
   
       if(nowSum == target){
   
           res.push_back(temp);
           return;
       }
       for(int i=id;i<candidates.size();i++){
   
           nowSum += candidates[i];
           if(nowSum > target
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值