[LeetCode] 47.順列II順列II(C ++)


トピックのソース:https//leetcode-cn.com/problems/permutations-ii/

タイトル説明

繰り返される番号を含むことができるシーケンス番号を指定すると、繰り返されないすべての順列を任意の順序で返します。

例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

一般的なアイデア

  • この質問はhttps://leetcode-cn.com/problems/permutations/にています。問題解決方法はバックトラッキング方法ですが、この質問にはバックトラッキング方法のプルーニング操作が必要です。
  • たとえば、1、配置全体を繰り返すことができる場合、3!の状況が発生しますが、繰り返される要素1があるため、現在の要素nums [i]がと同じである場合、繰り返される要素は配置から除外されます。前の要素nums [i-1]が繰り返され、前の要素はすでに配置れているため(used [i-1] == true)、この要素の再帰スタックは現在の要素の親ノードに返されます( node)を配置し、次に親再帰スタックがi ++をループし、次の要素を考慮します

バックトラッキングの概要

  • バックトラッキングはアルゴリズムのアイデアであり、再帰はプログラミング方法です。バックトラッキングは再帰によって実装できます。
  • バックトラッキング方法の全体的な考え方は次のとおりです:すべてのパスを検索し、各バックトラッキングは特定のパスを対象としています。現在の検索パスの下にある未探索の領域を検索するには、次の2つの状況が考えられます。
class Solution {
    
    
public:
    vector<vector<int>> ret;
    vector<int> ans;
    vector<bool> used;
    int n;
    vector<vector<int>> permuteUnique(vector<int>& nums) {
    
    
        n = nums.size();
        used.assign(n, false);
        sort(nums.begin(), nums.end());
        dfs(nums, 0);
        return ret;
    }
    void dfs(vector<int>& nums, int depth){
    
    
        if(depth == n){
    
    
            ret.push_back(ans);
            return;
        }
        for(int i = 0 ; i < n ; ++i){
    
    
            if(!used[i]){
    
    
                if(!ans.empty() && i - 1 >= 0 && nums[i - 1] == nums[i] && used[i - 1] == true)
                    return;
                used[i] = true;
                ans.push_back(nums[i]);
                dfs(nums, depth + 1);
                used[i] = false;
                ans.pop_back();
            }

        }
    }
};

複雑さの分析

  • 時間計算量:O(n * 2 ^ n)。nは配列の長さで、合計2 ^ nのケースがあり、作成にはO(n)時間がかかります。
  • スペースの複雑さ:O(n)。再帰的なスタックスペースは(n)です。

おすすめ

転載: blog.csdn.net/lr_shadow/article/details/114521077