【leetcode】【medium】46. Permutations

46. Permutations

Given a collection of distinct integers, return all possible permutations.

Example:

Input: [1,2,3]
Output:
[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

題目鏈接:https://leetcode-cn.com/problems/permutations/

 

思路

法一:回溯法

之前遇到的問題都是取連續的鏈,本題要取的元素並不連續。

這邊用了一個數組在標記元素是否用過了,能夠保證元素有重複值的情況也能使用。

class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> res;
        if(nums.size()<=0) return res;
        bool visit[nums.size()] = {false};
        return trace(nums, visit);
    }
    vector<vector<int>> trace(vector<int> nums, bool visit[]){
        vector<vector<int>> res;
        for (int i = 0; i<nums.size(); ++i){
            if(!visit[i]){
                visit[i] = true;
                auto vec = trace(nums, visit);
                visit[i] = false;
                if(vec.size()<=0){
                    vector<int> tmp = {nums[i]};
                    res.push_back(tmp);
                }else{
                    for(int j = 0; j<vec.size(); ++j){
                        vec[j].push_back(nums[i]);
                        res.push_back(vec[j]);
                    }
                }
            }
        }
        return res;
    }
};

代碼優化

上面的代碼是向下遞歸的時候進行了一次循環,返回結果後又對結果做了循環。

如果把兩次循環合併,不是把下面結果向上傳,而是上面的結果向下傳到底後直接儲存,可以降低運行時間。

class Solution {
public:
    vector<vector<int>> res;
    vector<vector<int>> permute(vector<int>& nums) {
        if(nums.size()<=0) return res;
        bool visit[nums.size()] = {false};
        vector<int> cur;
        trace(nums, 0, cur, visit);
        return res;
    }
    void trace(vector<int> nums, int index, vector<int> &cur, bool visit[]){
        if(index==nums.size()){
            res.push_back(cur);
            return;
        }
        for (int i = 0; i<nums.size(); ++i){
            if(!visit[i]){
                cur.push_back(nums[i]);
                visit[i] = true;
                trace(nums, index+1, cur, visit);
                visit[i] = false;
                cur.pop_back();
            }
        }
    }
};

法二:庫函數next_permutation

這個方法是看分享才知道的。說實話有點作弊,做筆試或比賽的時候可以用,面試的話肯定還會細問next_permutation的實現。

next_permutation(開始位置,結束位置-不包含):變換範圍 [first, last) 爲來自所有按相對於 operator< 或 comp 的字典序的下個排列。若這種排列存在則返回 true ,否則變換範圍爲首個排列(如同用 std::sort(first, last) )並返回 false 。

這種方法應該屬於特殊例子,沒有仔細調研來龍去脈,暫時先參考這篇博文的解釋學習了下,如果思路比較通用的話以後應該還會遇到,暫時先挖個坑背誦一下哈哈。

c++<algorithm>庫中的解釋:https://zh.cppreference.com/w/cpp/algorithm/next_permutation

代碼來源:https://leetcode-cn.com/problems/permutations/solution/hui-su-next_permutation-by-ogeazjciet/

vector<vector<int>> permute(vector<int>& nums) {        
    sort(nums.begin(), nums.end());
    do {
        result.push_back(nums);
    }while (next_permutation(nums.begin(), nums.end()));
    return result;
}

 

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