代码随想录算法训练营第17期第29天 | 491. 递增子序列、46. 全排列、 47. 全排列 II

491. 递增子序列

 本题重点:

1.本题仍然需要start_index,取完当前下标后的数据后,下个数据从+1开始;

2.这里题目要求【递增子序列中 至少有两个元素】,所以收集结果的判定是:

if(path.size() > 1)
{
    res.push_back(path);
}

3.搜索逻辑图如下:同一父节点下的同层上使用过的元素就不能再使用了

代码随想录算法训练营第17期第29天 | 491. 递增子序列、46. 全排列、 47. 全排列 II_第1张图片

所以:

         a.题目要求是递增子序列,所以,nums[i]要>=path.back(),故path里面必须要有值,所以,条件之一是【!path.empty() and nums[i] < path.back()】

        b.按照第三层的逻辑,前面取7组成【4,7】,当遇到第二个7的时候,就不取了,所以这里需要设置一个map,当然这里值少,用list也行,map的话,写法是【uset.find(nums[i]) != uset.end()】表示找到了,list的话,采用【int used[201] = {0};和used[nums[i]+100] == 1)】,因为这题的要求是【-100 <= nums[i] <= 100】,最多201个数;

        c.uset的写法不用回溯,这里要注意;这也是需要注意的点,unordered_set uset; 是记录本层元素是否重复使用,新的一层uset都会重新定义(清空),所以要知道uset只负责本层!

class Solution {
public:
    vector> res;
    vector path;
    void backtracking(vector& nums, int st_index){
        if(path.size() > 1){
            res.push_back(path);
        }
        unordered_set uset;
        for(int i = st_index; i < nums.size(); i++){
            if(!path.empty() and nums[i] < path.back() || uset.find(nums[i]) != uset.end()){
                continue;
            }
            uset.insert(nums[i]);
            path.push_back(nums[i]);
            backtracking(nums,i+1);
            path.pop_back();
        }
    }
    vector> findSubsequences(vector& nums) {
        backtracking(nums, 0);
        return res;

    }
};

46. 全排列

 本题重点: 

  1.  看了之前python的写法 ,因为本题有【不含重复数字】的设定,所以python可以用 not in 的机制来代替used的写法;
  2. 因为需要所有数据,每次都需要从头开始遍历,故不再需要start_index,i每次从0开始;
  3. 虽然每次从头遍历,但是用过的数据,就不再用了,所以这里引入used数据机制,不然就会出现[1,1,1]的情况;

代码随想录算法训练营第17期第29天 | 491. 递增子序列、46. 全排列、 47. 全排列 II_第2张图片

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

 

47. 全排列 II

 本题要点:

  1. 本题的重点就是去重,【i > 0 and nums[i] == nums[i-1] and used[i-1] == 0 】表示树层去重,当前数和之前一样,且之前没用被用到,这种情况肯定在之前就有了;【used[i] == 1】表示当前数已经被用过了,不用再取,往后取,这里是两种去重方式

代码随想录算法训练营第17期第29天 | 491. 递增子序列、46. 全排列、 47. 全排列 II_第3张图片

 

class Solution {
public:
    vector> res;
    vector path;
    void backtraking(vector& nums, vector& used){
        if (path.size() == nums.size()){
            res.push_back(path);
            return;
        }
        for(int i = 0; i < nums.size();i++){
            if(i > 0 and nums[i] == nums[i-1] and used[i-1] == 0 or used[i] == 1){
                continue;
            }
            path.push_back(nums[i]);
            used[i] = 1;
            backtraking(nums, used);
            used[i] = 0;
            path.pop_back();
        }
    }
    vector> permuteUnique(vector& nums) {
        sort(nums.begin(),nums.end());
        vector used(nums.size(), 0);
        backtraking(nums, used);
        return res;
    }
};

你可能感兴趣的:(算法,leetcode,数据结构)