件名のソース:https://leetcode-cn.com/problems/permutations/
タイトル説明
- 繰り返し番号のないシーケンスが与えられた場合、可能なすべての順列を返します。
例:
入力:[1,2,3]
出力:
[
[1,2,3
]、
[1,3,2]、
[2,1,3]、
[ 2,3,1]、[3,1 、2]、
[3,2,1]
]
一般的なアイデア
- これは古典的なバックトラッキングの問題と見なすことができ、可能なすべての完全な順列を返します。完全な順列の問題の場合、バックトラッキング方法を使用して解決できます(データ量が少ない場合、バックトラッキング方法の時間計算量は一般に高)、あなたはアイデアを参照することができます[以下のより詳細な問題解決策]
https://leetcode-cn.com/problems/permutations/solution/hui-su-suan-fa-python-dai-ma-java-dai -ma-by-liweiw /
バックトラック
- 従来のdpの問題では、アレンジメント内の要素の重複を防ぐために、boolを使用して、その要素がすでに現在のアレンジメントにあるかどうかを記録することができます。特定の再帰プロセスがわからない場合は、アレンジメントの内容を理解を深める【注意事項】
- 下の図の最初の数行の2と3は配置から削除されていますが、1は削除されていないことに注意してください。これは、2、i = 1を削除した後、現在の再帰スタックのforループを通過する必要があるためです。 、これは配置の次の要素nums [2] = 3であり、後続のプロセスは同様です
-
class Solution {
public:
vector<vector<int>> ret;
vector<int> ans;
vector<bool> used;
int n;
vector<vector<int>> permute(vector<int>& nums) {
n = nums.size();
used.assign(n, false);
dfs(nums, 0);
return ret;
}
void dfs(vector<int>&nums, int depth){
if(depth == n){
ret.push_back(ans);
return;
}
for(int j = 0; j < n ; ++j){
if(!used[j]){
ans.push_back(nums[j]);
used[j] = true;
//cout << "递归之前=> " << "\t" << depth << "\t";
//for (auto num : ans) {
// cout << num << ",";
//}
dfs(nums, depth + 1);
used[j] = false;
ans.pop_back();
//cout << "递归之后=> " << "\t" << depth << "\t";
//for (auto num : ans) {
// cout << num << ",";
//}
//cout << endl;
}
}
}
};
複雑さの分析
- 時間計算量:O(n * n!)。バックトラッキングの時間計算量は依然として非常に大きいことがわかります。最適化には、通常[プルーニング方法]があります。最初の要素が決定された後、後続のすべての要素のサイクル数、つまりn! (nの階乗)、Oが必要(n)の時間は、O(n * n!)である回答データにコピーされます。
- スペースの複雑さ:O(n)。使用されるすべてのデータはグローバル変数として設定されるため、ここではO(n)再帰スタックスペースのみが必要です。