「程式碼隨想錄演算法訓練營」第二十二天 | 回溯演算法 part4

云雀AC了一整天發表於2024-07-27

491. 非遞減子序列

題目連結:https://leetcode.cn/problems/non-decreasing-subsequences/
題目難度:中等
文章講解:https://programmercarl.com/0491.遞增子序列.html
影片講解:https://www.bilibili.com/video/BV1EG4y1h78v/
題目狀態:有思路,藉助 ChatGPT 透過

思路:

在之前程式碼的基礎上,新增一個set<vector<int>>型別的全域性變數,用來跟蹤已新增的子序列,來避免重複子序列的儲存。

程式碼:

class Solution {
public:
    vector<vector<int>> res;
    vector<int> vec;
    set<vector<int>> seen;
    
    void backtracking(vector<int> &nums, int startIdx) {
        if(vec.size() >= 2) {
            if(seen.find(vec) == seen.end()) {
                res.push_back(vec);
                seen.insert(vec);
            }
        }
        for(int i = startIdx; i < nums.size(); ++i) {
            if(vec.empty() || nums[i] >= vec.back()) {
                vec.push_back(nums[i]);
                backtracking(nums, i + 1);
                vec.pop_back();
            }
        }
    }
    vector<vector<int>> findSubsequences(vector<int>& nums) {
        backtracking(nums, 0);
        return res;
    }
};

46. 全排列

題目連結:https://leetcode.cn/problems/permutations/
題目難度:中等
文章講解:https://programmercarl.com/0046.全排列.html
影片講解:https://www.bilibili.com/video/BV19v4y1S79W/
題目狀態:有思路,藉助 ChatGPT 透過

思路:

定義一個全域性變數vector<bool> isUsed,用來判斷當前節點是否已經被回溯到了,若已經用過就直接跳過,之後使用回溯模板。

程式碼:

class Solution {
public:
    vector<vector<int>> res;
    vector<int> vec;
    vector<bool> isUsed;
    void backtracking(vector<int> &nums) {
        if(vec.size() == nums.size()) {
            res.push_back(vec);
            return;
        }
        for(int i = 0; i < nums.size(); ++i) {
            if(isUsed[i]) continue;
            vec.push_back(nums[i]);
            isUsed[i] = true;
            backtracking(nums);
            vec.pop_back();
            isUsed[i] = false;
        }
    }
    vector<vector<int>> permute(vector<int>& nums) {
        isUsed.resize(nums.size(), false);
        backtracking(nums);
        return res;
    }
};

47. 全排列II

題目連結:https://leetcode.cn/problems/permutations-ii/
題目難度:中等
文章講解:https://programmercarl.com/0047.全排列II.html
影片講解:https://www.bilibili.com/video/BV1R84y1i7Tm/
題目狀態:有思路,透過

思路:

將上面兩題結合一下,分別建立一個vector<bool>的全域性變數來判斷當前元素是否已經被使用,避免排列出來的單個結果中出現重複的元素;在定義一個set<vector<int>>的全域性變數,來判斷所有排列中是否出現了重複的排列方案。

程式碼:

class Solution {
public:
    vector<vector<int>> res;
    vector<int> vec;
    vector<bool> isUsed;
    set<vector<int>> seen;
    void backtracking(vector<int> &nums) {
        if(vec.size() == nums.size()) {
            if(seen.find(vec) == seen.end()) {
                res.push_back(vec);
                seen.insert(vec);
            }
        }
        for(int i = 0; i < nums.size(); ++i) {
            if(isUsed[i]) continue;
            vec.push_back(nums[i]);
            isUsed[i] = true;
            backtracking(nums);
            vec.pop_back();
            isUsed[i] = false;
        }
    }
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        isUsed.resize(nums.size(), false);
        backtracking(nums);
        return res;
    }
};

相關文章