面試題_回溯法

46. 全排列

給定一個不含重複數字的數組 nums ,返回其 所有可能的全排列 。你可以 按任意順序 返回答案。

示例 1:

輸入:nums = [1,2,3]
輸出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
示例 2:

輸入:nums = [0,1]
輸出:[[0,1],[1,0]]
示例 3:

輸入:nums = [1]
輸出:[[1]]

提示:
1 <= nums.length <= 6
-10 <= nums[i] <= 10
nums 中的所有整數 互不相同

class Solution {
    vector<vector<int> > ans;
    vector<int> t;
public:
    void dfs(vector<int>& nums, int cur, int nlen, vector<int>& used)
    {
        if (cur == nlen) {
            ans.push_back(t);
            return;
        }
        for(int i = 0; i < nlen; ++i)
        {
            if (!used[i]) {
                t.push_back(nums[i]);
                used[i] = true;
                dfs(nums, cur + 1, nlen, used);
                t.pop_back();
                used[i] = false;
            }
        }
    }
    vector<vector<int>> permute(vector<int>& nums) {
        int nlen = nums.size();
        vector<int> used(nlen);
        dfs(nums, 0, nlen, used);
        return ans;
    }
};
class Solution {
public:
    void dfs(vector<vector<int> >& ans, vector<int>& nums, int first, int nlen)
    {
        if (first == nlen) {
            ans.emplace_back(nums);
            return;
        }
        for(int i = first; i < nlen; ++i)
        {
            swap(nums[i], nums[first]);
            dfs(ans, nums, first + 1, nlen);
            swap(nums[i], nums[first]);
        }
    }
    vector<vector<int>> permute(vector<int>& nums)
    {
        vector<vector<int> > ans;
        int nlen = nums.size();
        dfs(ans, nums, 0, nlen);
        return ans;
    }
};

複雜度分析

  • 時間複雜度:\(O(n\times n!)\),其中 n 爲序列的長度。
  • 空間複雜度:O(n)

47. 全排列 II

給定一個可包含重複數字的序列 nums ,按任意順序 返回所有不重複的全排列。

示例 1:

輸入:nums = [1,1,2]
輸出:
[[1,1,2],
[1,2,1],
[2,1,1]]
示例 2:

輸入:nums = [1,2,3]
輸出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

提示:
1 <= nums.length <= 8
-10 <= nums[i] <= 10

class Solution {
    vector<int> vis;
public:
    void dfs(vector<vector<int> >& ans, vector<int>& nums, int cur, int nlen, vector<int>& perm)
    {
        if (cur == nlen) {
            ans.emplace_back(perm);
            return;
        }
        for (int i = 0; i < nlen; ++i)
        {
            if(vis[i] || (i > 0 && nums[i - 1] == nums[i] && vis[i - 1])) {
                continue;
            }
            perm.emplace_back(nums[i]);
            vis[i] = 1;
            dfs(ans, nums, cur + 1, nlen, perm);
            vis[i] = 0;
            perm.pop_back();
        }
    }
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<int> perm;
        vector<vector<int> > ans;
        int nlen = nums.size();
        vis.resize(nlen);
        sort(nums.begin(), nums.end());
        dfs(ans, nums, 0, nlen, perm);
        return ans;
    }
};

複雜度分析

  • 時間複雜度:\(O(n\times n!)\),其中 n 爲序列的長度。
  • 空間複雜度:O(n)

法二:下一個排列(最優)

class Solution {
public:
    bool nextpermute(vector<int>& nums)
    {
        int i = nums.size() - 2;
        while (i >= 0 && nums[i] >= nums[i + 1]) i--;
        if (i < 0) return false;
        int j = nums.size() - 1;
        while (j >= 0 && nums[i] >= nums[j]) j--;
        if (j < 0) return false;
        swap(nums[i], nums[j]);
        reverse(nums.begin() + i + 1, nums.end());
        return true;
    }
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<vector<int> > ans;
        sort(nums.begin(), nums.end());
        do {
            ans.emplace_back(nums);
        } while (nextpermute(nums));
        return ans;
    }
};

時間複雜度:O(n!n)
空間複雜度: \(O(1)\)

劍指 Offer 38. 字符串的排列

輸入一個字符串,打印出該字符串中字符的所有排列。

你可以以任意順序返回這個字符串數組,但裏面不能有重複元素。

示例:

輸入:s = "abc"
輸出:["abc","acb","bac","bca","cab","cba"]

限制:
1 <= s 的長度 <= 8

class Solution {
    vector<int> vis;
public:
    void dfs(vector<string>& ans, const string& s, int cur, int slen, string& perm)
    {
        if(cur == slen) 
        {    
            ans.emplace_back(perm);
            return;
        }
        for (int i = 0; i < slen; ++i)
        {
            if(vis[i] || (i > 0 && s[i] == s[i - 1] && vis[i - 1])) {
                continue;
            }
            perm.push_back(s[i]);
            vis[i] = 1;
            dfs(ans, s , cur + 1, slen, perm);
            vis[i] = 0;
            perm.pop_back();
        }
    }
    vector<string> permutation(string s) {
        int slen = s.size();
        vis.resize(slen);
        vector<string> ans;
        string perm;
        sort(s.begin(), s.end());
        dfs(ans, s, 0, slen, perm);
        return ans;
    }
};

時間複雜度:O(n!n)
空間複雜度: \(O(n)\)

方法二:用set去重

class Solution {
    vector<string> ans;
public:
    void dfs(string& s, int cur, int slen)
    {
        if (cur == slen - 1) {
            ans.emplace_back(s);
            return;
        }
        unordered_set<int> uset;
        for(int i = cur; i < slen; i++)
        {
            if (uset.find(s[i]) != uset.end()) {
                continue;
            }
            uset.insert(s[i]);
            swap(s[i], s[cur]);
            dfs(s, cur + 1, slen);
            swap(s[i], s[cur]);
        }
    }
    vector<string> permutation(string s) {
        
        dfs(s, 0, s.length());
        return ans;
    }
};

時間複雜度:O(n!n)
空間複雜度: \(O(n^2)\)

方法三:下一個排列(最優)

class Solution {
public:
    bool nextPermutation(string& s) {
        int i = s.size() - 2;
        while (i >= 0 && s[i] >= s[i + 1]) {
            i--;
        }
        if (i < 0) {
            return false;
        }
        int j = s.size() - 1;
        while (j >= 0 && s[i] >= s[j]) {
            j--;
        }
        swap(s[i], s[j]);
        reverse(s.begin() + i + 1, s.end());
        return true;
    }

    vector<string> permutation(string s) {
        vector<string> ret;
        sort(s.begin(), s.end());
        do {
            ret.push_back(s);
        } while (nextPermutation(s));
        return ret;
    }
};

時間複雜度:O(n!n)
空間複雜度: \(O(1)\)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章