Day 又不知是day几 | 回溯算法part3

90.子集II

有点像子集I和之前做过的一个去重的结合
记得先排序

class Solution {
public:
    vector<vector<int>> result;
    vector<int> each;
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        vector<bool> used(nums.size(), false);
        nums.push_back(0);
        backTrace(nums, 0, used);
        return result;
    }
    void backTrace (vector<int>& nums, int index, vector<bool> used){
        int n = nums.size();
        if(index >= n){
            result.push_back(each);
            return;
        }

        for(int i = index; i< n; ++i){
            if(i == n-1 && nums[i]==0){
                backTrace(nums, i+1, used);
            }
            else if(i > 0 && nums[i]==nums[i-1] && used[i-1] == false){
                continue;
            }
            else{
                each.push_back(nums[i]);
                used[i]=true;
                backTrace(nums, i+1, used);
                used[i]=false;
                each.pop_back();
            }
        }
    }
};

A c 下一题

491.非递减子序列

这题不能sort
要按原来顺序给出非递减子序列

而本题求自增子序列,是不能对原数组进行排序的,排完序的数组都是自增子序列了。

所以不能使用之前的去重逻辑!

这里的去重就不使用used数组,而是在每层用一个哈希表去重(也不需要传参,在本层不重复就可以)

class Solution {
public:
    vector<vector<int>> result;
    vector<int> each;
    vector<vector<int>> findSubsequences(vector<int>& nums) {
        nums.push_back(0);
        backTrace(nums, 0);
        return result;
    }
    void backTrace(vector<int>& nums, int index) {
        int n = nums.size();
        unordered_set<int> set;
        if (index >= n) {
            if (each.size() >= 2) {
                result.push_back(each);
            }
            return;
        }
        for (int i = index; i < n; ++i) {
            if (i == n - 1 && nums[i] == 0) {
                backTrace(nums, i + 1);
            } else if (set.find(nums[i]) == set.end() &&
                       (each.size() == 0 || each[each.size() - 1] <= nums[i])) {
                set.insert(nums[i]);
                each.push_back(nums[i]);
                backTrace(nums, i + 1);
                each.pop_back();
            }
        }
    }
};

本层回溯逻辑:
插入的元素要大于等于当前each数组最后一个元素,或者each为空可以直接插入,
同时需要在哈希表中没出现过的元素(本层新建哈希表,不需要传参)
同时考虑可能这层啥也不选的可能(在nums最后添0)

46.全排列

需要回头找,所以不用设置index,反而用used数组来纵向(在递归过程中而非在本层中)表示哪些是被选择过的

class Solution {
public:
    vector<vector<int>> result;
    vector<int> each;
    vector<vector<int>> permute(vector<int>& nums) {
        vector<bool> used(nums.size(), false);
        backTrace(nums, used);
        return result;
    }
    void backTrace(vector<int>& nums, vector<bool> used) {
        int n = nums.size();

        if (each.size() == n) {
            result.push_back(each);
            return;
        }
        for (int i = 0; i < n; ++i) {
            if (used[i] == false) {
                each.push_back(nums[i]);
                used[i] = true;
                backTrace(nums, used);
                used[i] = false;
                each.pop_back();
            }
        }
    }
};

47.全排列 II

先sort后用used,在本层横向和递归纵向都去重的结合

class Solution {
public:
    vector<vector<int>> result;
    vector<int> each;
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        vector<bool> used(nums.size(), false);
        backTrace(nums,used);
        return result;
    }
    void backTrace(vector<int>& nums, vector<bool>& used){
        int n = nums.size();
        if(each.size() == n){
            result.push_back(each);
            return;
        }

        for(int i = 0; i<n; ++i){
            if(used[i] == true || (i>0 && used[i-1]==false && nums[i]==nums[i-1])){
                continue; 
            }
            else{
                used[i]=true;
                each.push_back(nums[i]);
                backTrace(nums,used);
                each.pop_back();
                used[i]=false;
            }
        }
    }
};

Ac
开启回溯算法最后一part!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值