トピックのソース: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)です。