トピック:
繰り返される要素を含む可能性のある整数配列numsを指定すると、配列のすべての可能なサブセット(べき集合)を返します。
注:ソリューションセットに重複するサブセットを含めることはできません。
例:
入力:[1,2,2]
出力:
[
[2]、
[1]、
[1,2,2]、
[2,2]、
[1,2]、
[]
]
ソース:
問題解決のアイデア:バックトラック
出力配列のすべての可能なサブセットを参照し 、 コードの上に重複排除コードの行を追加します。while(i + 1 <nums.size()&& nums [i + 1] == nums [i])i ++;
組み合わせプロセスの説明は次のとおりです。5桁から3桁を任意に選択した場合、1桁を選択した後、後で選択する番号は現在の桁の後になります。次の図に示すように、2を選択した場合、その後の数字は3、4、5になります。
2と3を選択した場合は、4を選択して出力した後、選択した4を削除して5に置き換える必要があります。番号を選択し、再帰的に処理して、番号を削除します。このプロセスはバックトラックです。
番号が繰り返される場合、番号が最初にソートされます.1、2、2、3、3、4、5のシーケンスがある場合、2番目の番号2で構成されるツリー構造は、最初のツリー構造の一部になります。したがって、ループ内の同じ番号をスキップするだけです。
コードは次のように表示されます。
class Solution {
public:
vector< vector<int> > result;
vector<int> path;
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
for (int i = 0; i <= nums.size(); i++) {
back(nums, 0, i);
}
return result;
}
void back(const vector<int>& nums, int start, int k) {
if (path.size() == k) {
result.push_back(path);
return;
}
for (int i = start; i < nums.size(); i++) {
if (path.size() + nums.size() - i + 1 < k) break;
path.push_back(nums[i]);
back(nums, i+1, k);
path.pop_back();
while (i+1<nums.size() && nums[i+1] == nums[i]) i++; // 增加这一行,去重
}
}
};