代码随想录算法训练营第二十九天【回溯算法part05】 | 491.递增子序列、46.全排列、47.全排列 II

491.递增子序列

题目链接:

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

求解思路:

注意事项

  • 不能排序

回溯三部曲

  1. 递归函数参数:数组nums,起始编号startIndex
  2. 终止条件:可以不加终止条件,因为我们要遍历树形结构;需要加一个判断来收集符合要求的结果
  3. 单层搜索逻辑:同一父节点上的同层上使用过的元素就不能再使用了;使用set来记录某个数是否被用过,注意递归函数下面没有对应的pop,这是因为 unordered_set uset 写在for循环的上面,每一层都会重新定义(清空)

图解

代码随想录算法训练营第二十九天【回溯算法part05】 | 491.递增子序列、46.全排列、47.全排列 II_第1张图片

代码:

class Solution {
private:
    vector path;
    vector> result;
    void backtracking(vector& nums, int startIndex){
        if (path.size() >= 2)
            result.push_back(path); // 收获结果
        unordered_set uset; // 新的一层的uset会重新定义(清空)
        for (int i = startIndex; i < nums.size(); i++){
            // path为空 && 当前值小于path的最后一个值 || set中有这个数字(说明被用过了)
            if (!path.empty() && 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();
        }
    }
public:
    vector> findSubsequences(vector& nums) {
        result.clear();
        path.clear();
        backtracking(nums, 0);
        return result;
    }
};

46.全排列

题目链接:

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

求解思路:

回溯三部曲

  1. 递归函数参数:数组nums,bool类型数组used(用于判断数是否被用过)
  2. 终止条件:path的长度等于nums
  3. 单层搜索的逻辑:每次从0开始搜索,一个排列里一个元素只能使用一次

图解

代码随想录算法训练营第二十九天【回溯算法part05】 | 491.递增子序列、46.全排列、47.全排列 II_第2张图片

代码:

class Solution {
private:
    vector path;
    vector> result;
    void backtracking(vector& nums, vector& 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]);
            backtracking(nums, used);
            path.pop_back();
            used[i] = false;
        }
    }
public:
    vector> permute(vector& nums) {
        vector used(nums.size(), false);
        result.clear();
        path.clear();
        backtracking(nums, used);
        return result;
    }
};

47.全排列 II

题目链接:

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

求解思路:

在 46.全排列 的基础上加入去重。

去重过程图解

代码随想录算法训练营第二十九天【回溯算法part05】 | 491.递增子序列、46.全排列、47.全排列 II_第3张图片

代码:

class Solution {
private:
    vector path;
    vector> result;
    void backtracking(vector& nums, vector& 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]);
                backtracking(nums, used);
                path.pop_back();
                used[i] = false;
            }
        }
    }
public:
    vector> permuteUnique(vector& nums) {
        result.clear();
        path.clear();
        sort(nums.begin(), nums.end());
        vector used(nums.size(), false);
        backtracking(nums, used);
        return result;
    }
};

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