代码随想录Day29 | 491.递增子序列 46.全排列 47.全排列 II

代码随想录Day29 | 491.递增子序列 46.全排列 47.全排列 II

491.递增子序列

文档讲解:代码随想录
视频讲解: 回溯算法精讲,树层去重与树枝去重 | LeetCode:491.递增子序列
状态

对于不可先行排序数组的去重操作,利用哈希表记录是否出现过。利用哈希表对每一层的元素进行记录,如果存在表示之前使用过,就不用再遍历这个分支了

//至少从第二层开始记录
//遇到比最后一个小的就要返回

class Solution {

private:
    vector<vector<int>> res;
    vector<int> path;
public:
    void getSeq(vector<int>& nums, int startIndex)
    {
        if(path.size()>1)
        {
            res.push_back(path);
        }
        if(startIndex == nums.size())
        {
            return;
        }
        unordered_set<int> checkset; // 对每一层的元素使用情况进行统计, 可以优化为数组
        for(int i = startIndex;i<nums.size();i++)
        {
            //当路径数组不为空,要添加元素小于路径最后一个元素,这个元素已经被搜寻过,就跳过不插入
            if(!path.empty() && nums[i]<path.back() || checkset.find(nums[i])!=checkset.end())
            {
                continue;
            }
            checkset.insert(nums[i]);
            path.push_back(nums[i]);
            getSeq(nums,i+1);
            path.pop_back();
        }

    }
public:
    vector<vector<int>> findSubsequences(vector<int>& nums) {
        getSeq(nums,0);
        return res;
    }
};

46.全排列

文档讲解:代码随想录
视频讲解: 组合与排列的区别,回溯算法求解的时候,有何不同?| LeetCode:46.全排列
状态

排列与顺序相关,所以之前在组合中使用的决定下一层开始位置的元素就不需要了,因为每次都是从0开始,唯一需要注意的是,上一层用过的元素,下一层应当去掉,所以我们使用一个used数组,在组合去重问题中,我们是考虑同一层,现在需要考虑是同一个树枝,如果其在下一层为1,那么说明上一层用过,应当跳过。

//排列:考虑顺序,startIndex永远从0开始

class Solution {
private:
    vector<vector<int>> res;
    vector<int> path;
public:
    void getPer(vector<int>& nums,vector<int> used)
    {
        if(path.size() == nums.size())
        {
            res.push_back(path);
            return;
        }
        for(int i = 0; i<nums.size();i++)
        {
            //上一层使用过,则这一层跳过它
            if(used[i] == 1)
            {
                continue;
            }
            used[i] = 1;
            path.push_back(nums[i]);
            getPer(nums,used);
            path.pop_back();
            used[i] = 0;
        }
        return ;
    }
public:
    vector<vector<int>> permute(vector<int>& nums) {
        vector<int> used(nums.size());
        getPer(nums,used);
        return res;
    }
};

47.全排列II

文档讲解:代码随想录
视频讲解: 回溯算法求解全排列,如何去重?| LeetCode:47.全排列 II
状态

这道题又需要去重,相当于同一层去除之前用过的元素,同一树枝去除上一层的元素

class Solution {
private:
    vector<vector<int>> res;
    vector<int> path;
public:
    void getPer(vector<int>& nums,vector<int> used)
    {
        if(path.size() == nums.size())
        {
            res.push_back(path);
            return;
        }
        for(int i = 0;i<nums.size();i++)
        {
            //同一层
            if(i>0 && used[i-1] == 0 && nums[i-1] == nums[i])
            {
                continue;
            }
            //同一树枝
            if(used[i] == 1)
            {
                continue;
            }
            used[i] = 1;
            path.push_back(nums[i]);
            getPer(nums,used);
            path.pop_back();
            used[i]=0;
        }
        return;
    }
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<int> used(nums.size());
        sort(nums.begin(),nums.end());
        getPer(nums,used);
        return res;
    }
};
  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值