[バックトラッキング] [leetcode]配列のすべての可能なサブセットを出力します(重複する要素を含む)

トピック:

繰り返される要素を含む可能性のある整数配列numsを指定すると、配列のすべての可能なサブセット(べき集合)を返します。

注:ソリューションセットに重複するサブセットを含めることはできません。

例:

入力:[1,2,2]
出力:
[
  [2]、
  [1]、
  [1,2,2]、
  [2,2]、
  [1,2]、
  []
]

ソース:

90. 子集 II

問題解決のアイデア:バックトラック

出力配列のすべての可能なサブセットを参照し  コードの上に重複排除コードの行を追加します。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++; // 增加这一行,去重
        }
    }
};

 

おすすめ

転載: blog.csdn.net/hbuxiaoshe/article/details/115013103