代码随想录 第七章 回溯算法 part04 简单部分 491.递增子序列 46.全排列47.全排列 II

491.递增子序列

class Solution {
private:
    vector<vector<int>>result;
    vector<int>path;
    void bt(vector<int>& nums, int l){
        if(l==nums.size()) return;
        unordered_set<int>used;
        for(int i=l;i<nums.size();i++){
            if(used.find(nums[i])!=used.end()) continue;
            path.push_back(nums[i]);
            used.insert(nums[i]);
            if(path.size()>1){
                if(path[path.size()-1]<path[path.size()-2]){
                    path.pop_back();
                    continue;
                }
                result.push_back(path);
            }
            bt(nums,i+1);
            path.pop_back();
        }
    }
public:
    vector<vector<int>> findSubsequences(vector<int>& nums) {
        bt(nums,0);
        return result;
    }
};

这题笔者对回溯的处理稍有不同,并不是将path加入result与退出一层回溯绑定,这样就不需要再回溯中加一个参数记录还需要回溯几层,而是将同起点元素的全部答案全部找出后,更换起点。这题与此前的求组合也不同,在于这题要得到子序列,所以不能通过排序的手段去重,所以就再每层回溯中增加一个哈希表,记录曾经作为过起点的元素,再之后的循环中遇到哈希表中存在的匀速就跳过本轮循环,直接进入下一轮。可以这样去重的原理在于,访问到的哈希表中不存在的元素,是相同元素中索引最小的,意味着这一元素再次出现时,剩余序列是第一次出现时剩余序列的子序列,所以在第一次出现时,就可以将该元素作为起始的所有递增序列全部求出来。

46.全排列

class Solution {
private:
    vector<vector<int>>result;
    vector<int>path;
    void bt(vector<int>& nums){
        if(nums.size()==0){
            result.push_back(path);
            return;
        }
        for(int i=0;i<nums.size();i++){
            path.push_back(nums[i]);
            nums.erase(nums.begin()+i);
            bt(nums);
            nums.insert(nums.begin()+i,path[path.size()-1]);
            path.pop_back();
        }
    }
public:
    vector<vector<int>> permute(vector<int>& nums) {
        bt(nums);
        return result;
    }
};

构造循环,逐个取出元素加入path,并从nums中删除后,进入下一层回溯,下一层回溯退出后,将元素插回nums原位置,并从path中删除,是否将path加入result的判断标准是nums是否为空。

47.全排列 II

class Solution {
private:
    vector<vector<int>>result;
    vector<int>path;
    void bt(vector<int>& nums){
        if(nums.size()==0){
            result.push_back(path);
            return;
        }
        int pre=11;
        for(int i=0;i<nums.size();i++){
            if(nums[i]==pre) continue;
            else pre=nums[i];
            cout<<i;
            path.push_back(nums[i]);
            nums.erase(nums.begin()+i);
            bt(nums);
            nums.insert(nums.begin()+i,path[path.size()-1]);
            path.pop_back();
        }
    }
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        bt(nums);
        return result;
    }
};

这题就是传统艺能,通过对nums排序,在每层回溯中只将第一次出现的元素作为可以加入path的元素,对结果进行去重。

代码随想录 第七章 回溯算法 part04

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值