难搞的recursion(dfs模板)(C++)

题外话:回溯其实不难,不要自己吓自己!
报错出错的真相只有一个!凶手就是混乱的逻辑!

回溯问题需要想清楚:

  1. 子问题是什么:对于这个子问题,你有什么(传递内容)
  2. 结束条件是什么:如何跳出回溯
  3. 回溯条件是什么:进入下一个自问题的判断条件是什么

22. Generate Parentheses

https://leetcode.com/problems/generate-parentheses/.
最最最简单的回溯,可以当作模板记。

子问题:给定一串字符串(path),例如现在"(("里包含两个左括号,现在要么结束,要么在后面加内容。

结束条件:
字符串里左右括号的数量(left,right)是不是达到了n
yes -> 结束,并把得到的字符串添加到==结果(res)==里
no -> 需要继续

现在需要继续了,左括号的数量是否达到n
yes -> 加右括号
no -> 加左括号(⚠️加左括号的时候需要判断左括号数量(left)是否大于右括号数量(right),因为当path="(())",这时候只能加左括号,right大于left需要直接return)

⚠️注意区分res和path。


class Solution {
public:
    vector<string> generateParenthesis(int n) {
        vector<string> res;
        string path="";
        dfs(res,path,n,0,0);
        return res;
    }
    
    void dfs(vector<string>& res,string path,int n,int left,int right){
        //stop
        if (left==n && right==n){
            res.push_back(path);
            return;
        }
        //continue
        if (left<n)
            dfs(res,path+'(',n,left+1,right);
        if (left>right)
            dfs(res,path+')',n,left,right+1);
    }
};

参考:https://blog.csdn.net/fuxuemingzhu/article/details/79362373.

39. Combination Sum

https://leetcode.com/problems/combination-sum/.
纪念一下差点第一次完整的写出了这类问题,除了有一个地方没注意⚠️:就是dfs()里的path和res都是会一直保持不变了,退回上一个dfs()函数时,path/res不会退回到上一个状态的值(我也不知道我这个奇怪的思想是怎么来的)

class Solution {
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        vector<vector<int>> res={};
        vector<int> path={};
        dfs(candidates,target,res,path);
        return res;
    }
    
    
    void dfs(vector<int>& data, int target, vector<vector<int>>& res, vector<int>& path){
        int sum = accumulate(path.begin(), path.end(), 0);
        int N=data.size();
        if (sum==target){
            res.push_back(path);
            return;
        }
        else if (sum>target)
            return;
        else{
            for (int i=0;i<N;++i){
                path.push_back(data[i]);//每一次退回,path不会退回上一次函数里path的值
                
                vector<int> copy(data.begin()+i,data.end());
                dfs(copy,target,res,path);
                path.pop_back();//所以需要pop_back!⚠️
            }
        }           
    }
};

参考:https://blog.csdn.net/fuxuemingzhu/article/details/79322462.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值