代码随想录训练营第25天 || 491. 非递减子序列 46. 全排列 47. 全排列 II

491. 非递减子序列

讲解:代码随想录

思路:

递归:抽象为一颗树,不能使用标记数组进行去重,因为不能排序,所以使用一个集合来去重,如果使用过就放入集合,每当取数时,如果在集合中找到,就跳过当前数,来去重,注意集合是每遍历层就会重置,这一步很巧妙,避免同层重复。

代码:

class Solution {
    vector<vector<int>> result;
    vector<int> path;
private:
    void caozuo(vector<int>& nums,int startindex)
    {
        if(path.size()>=2)
        {
            result.push_back(path);
        }
        unordered_set<int> uset;巧妙,在此重置每当进入下一层时都会重置set
        for(int i =startindex ;i<nums.size();i++)
        {
            if((!path.empty() && nums[i] < path.back())|| uset.find(nums[i])!= uset.end())//back()表示末尾元素 ,find()函数会查找括号内的值,如果找到会返回下标的迭代器,如果没找到会返回end()的迭代器
            {
                continue;
            }
            uset.insert(nums[i]);
            path.push_back(nums[i]);
            caozuo(nums,i+1);
            path.pop_back();
        }
    }
public:
    vector<vector<int>> findSubsequences(vector<int>& nums) {
      result.clear();
      path.clear();
      caozuo(nums,0);
      return result;  
    }
};

遇到的问题:

1.对于集合初始化的位置选择,每当进入下一层时都会重置set

2.cpp的find()函数,会查找指定容器内某个范围的指定数值的迭代器,如果没有查找到会返回容器末尾的迭代器。find(要查找范围的开头,要查找范围的末尾,查找的数值)

46. 全排列

讲解:代码随想录

思路:

递归:因为集合内每个元素只能使用一次,所以需要进行树枝去重,没有重复元素所以不需要进行树层去重

代码:

class Solution {
    vector<vector<int>> result;
    vector<int> path;
private:
    void caozuo(vector<int>& nums,vector<bool> used)
    {
        if(path.size() == nums.size())
        {
            result.push_back(path);
            return;
        }
        for(int i =0;i<nums.size();i++)
        {
            if(used[i] == true)
            {
                continue;
            }
            used[i]=true;
            path.push_back(nums[i]);
            caozuo(nums,used);
            path.pop_back();
            used[i] = false;
        }
    }
public:
    vector<vector<int>> permute(vector<int>& nums) {
        result.clear();
        path.clear();
        vector<bool> used(nums.size(), false);
        caozuo(nums, used);
        return result;
    }
};

遇到的问题:

1.对于树枝去重和树层去重的理解

47. 全排列 II

讲解:代码随想录

思路:

递归:相比于上一题,因为原数组有了重复的数,但是结果又不能有重复的,所以不光需要树枝去重,还需要树层去重

代码:

class Solution {
private:
    vector<vector<int>> result;
    vector<int> path;
    void caozuo(vector<int>& nums,vector<bool>& used)
    {
        if(path.size() == nums.size())
        {
            result.push_back(path);
            return;
        }
        for(int i = 0;i<nums.size(); i++)
        {
            if(i> 0 && nums[i]==nums[i-1] && used[i-1]==false)
            {
                continue;
            }
            if(used[i]==false)
            {
                used[i] = true;
                path.push_back(nums[i]);
                caozuo(nums,used);
                path.pop_back();
                used[i] = false;
            }
        }
    }
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        result.clear();
        path.clear();
        sort(nums.begin(), nums.end()); // 排序
        vector<bool> used(nums.size(), false);
        caozuo(nums, used);
        return result;
    }
};

遇到的问题:

1.对于树枝去重的不同形式:因为此题同时进行了树枝去重和树层去重,所以此处树枝去重这样写的if(used[i]==false)
            {
                used[i] = true;
                path.push_back(nums[i]);
                caozuo(nums,used);
                path.pop_back();
                used[i] = false;
            }

2..只要是树层去重,使用标记数组,就要进行排序:原因是如果不排序,重复的元素不会相邻,这样就没法通过查找标记数组来确定,是树层的遍历,还是树枝的遍历

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值