力扣●93.复原IP地址 ●78.子集 ●90.子集II

●93.复原IP地址
这道题跟回文子串切割差不多的结构,但是剪枝有好几个地方。
而且我这个用了path单独放子串,然后回溯用substr删除递归前面加上的子串,时间空间复杂度有点高。得再改进改进。
class Solution {
public:
    string path;
    vector<string> result;
    int numPoint=0;//小数点的数量
    void backtracking(const string &s,int startIndex){
        if(startIndex==s.size() && numPoint==3){//numPoint>3的也被剪枝了
            result.push_back(path);
            return;
        }
        for(int i=startIndex;i<s.size();++i){
            const string sub=s.substr(startIndex,i-startIndex+1);
            if(sub.size()>3)continue;//剪枝1
            long long num=stoi(sub);
            if((sub[0]=='0'&&sub.size()>1)||num>255)continue;//剪枝2
            path+=sub;
            if(i<s.size()-1){
                path+='.';
                numPoint++;
            }

            backtracking(s,i+1);

            int len=i-startIndex+1;
            if(i<s.size()-1){
                path=path.substr(0,path.size()-len-1);
                numPoint--;
            }
            else path=path.substr(0,path.size()-len);
        }
    }
    vector<string> restoreIpAddresses(string s) {
        backtracking(s,0);
        return result;
    }
};


●78.子集

结构图如下,和之前的组合子串等的区别就是:组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点!(代码随想录原话)。

所以在函数开头不能写递归出口return出去,而是无论什么节点,都要加入到result里面。所以任何节点都是完整执行函数的开头到结尾才会退出。

class Solution {
public:
    vector<int> path;
    vector<vector<int>> result;
    void backtracking(vector<int>& nums,int startIndex){
        // if(startIndex==index){
           
        //     return;
        // }
        result.push_back(path);
        for(int i=startIndex;i<nums.size();++i){
            path.push_back(nums[i]);
             
            backtracking(nums,i+1);
            path.pop_back();
        }
    }
    vector<vector<int>> subsets(vector<int>& nums) {
        //result.push_back(path);
        backtracking(nums,0);
        return result;
    }
};

●90.子集II

就是●78.子集和● 40.组合总和II的结合,没有新的东西,必须秒了。

class Solution {
public:
    vector<int> path;
    vector<vector<int>> result;
    void backtracking(vector<int>& nums,int startIndex,vector<bool> &used){
        result.push_back(path);
        for(int i=startIndex;i<nums.size();++i){
            if(i>0 && nums[i]==nums[i-1] && used[i-1]==false)//剪枝
            {
                continue;
            }
            path.push_back(nums[i]);     
            used[i]=true;       

            backtracking(nums,i+1,used);

            used[i]=false; 
            path.pop_back();
        }
    }
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        vector<bool> used(nums.size()); 
        sort(nums.begin(),nums.end());
        fill(used.begin(),used.end(),false);
        backtracking(nums,0,used);
        return result;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值