組み合わせ合計 II (バックトラッキング、重複排除)

40. 組み合わせ和Ⅱ - LeetCode

質問の説明

一連の候補番号 candidates とターゲット番号 target を指定すると、 candidates 内のすべての候補を見つけます。数値の合計は target の組み合わせになります。

candidates の各数値は、各組み合わせで  1 回のみ 使用できます。

注: ソリューション セットには、繰り返しの組み合わせを含めることはできません。 

サンプル入力

例 1:

入力: 候補 = [10,1,2,7,6,1,5]、ターゲット = 8
出力:
[
[1,1,6]、
[1,2,5]、
[1,7]、
[2,6]
]

例 2:

入力: 候補 = [2,5,2,1,2]、ターゲット = 5、
出力:
[
[1,2,2]、
[5]
]

ヒント:

  • 1 <= candidates.length <= 100
  • 1 <= candidates[i] <= 50
  • 1 <= target <= 30

答え

この質問とこの質問 の合計 (バックトラッキング) - CSDN ブログの違いは、candidates 候補セット には繰り返しの要素がありますが、解セットには繰り返しの組み合わせが含まれない必要があるため、 解セットの重複を排除する必要があります。

たとえば、以下に示すように候補 = [10,1,2,7,6,1,5]、ターゲット = 8 の場合、明らかに [1,7 ]は解セットですが、 candidates には 2 つの要素 1、つまり図のポインタ a とポインタ c があります。要素をポイントする場合、バックトラッキング手法を使用してトラバースすると、必然的に2 つの解セット [1,7] が存在し、1 つは [a,b]、もう 1 つは [b,c] になります。 ] 質問の意味と矛盾します ですが、それらはすべて解決策セット [1,7] であり、

重複排除について 

まず候補配列を並べ替え、次のシーケンスを取得します:

次に、 バックトラッキング メソッドを使用して、並べ替えられた候補をスキャンします。隣接する同一の要素が見つかった場合 (candidates[i-1]==candidates[i])、スキップします。 。

次の疑問は、バックトラッキング メソッドでこのプロセスをどのようにシミュレートするかということです。

問題の説明を容易にするために、候補 =[1,1,2]、ターゲット =3 と仮定します。

下の図に示すように、並べ替えられた候補が隣接する同一の要素に遭遇した場合、候補[i-1]==候補[i]が存在する必要があります。しかし、問題はこの場合、同じブランチの下の の深度トラバーサルの合計です。同じ層の水平走査が発生し、必要な重複排除は同じツリー層の重複排除です。つまり、同じ層の走査では、candidate[i-1]==candidates[i] の場合にスキップされます。 』に遭遇。

これら 2 つの状況を区別するために、used 補助配列を使用して各数値フェッチのプロセスを記録します。つまり、数値が毎回フェッチされる場合、used の対応する位置が true に設定されます。

以下の図からわかるように、candidates[i] ==candidates[i - 1] の場合も同じ状況が発生します。

used[i - 1] == true、同じブランチ上の候補[i - 1] が使用されていることを示します
used[i - 1] == false、同じブランチ上の候補[i - 1] が使用されていることを示します同じツリー レイヤー上の候補 [i - 1] 使用

したがって、要件を満たす重複排除プロセスは次のように表すことができます。

候補者[i] == 候補者[i - 1] および used[i - 1] == false の場合、前のブランチは候補者[i - 1] を使用しました。つまり、同じツリー層が候補者を使用しました。 [i-1]。

このとき、for ループ内で continue 操作を実行する必要があります。

used[i - 1] == false が同じツリー レベルを意味するのはなぜですか? used[i - 1] == false だけが同じツリー レベルを表すことができるからです。現在フェッチされている候補者[i] は候補者[i - 1] からバックトラックされます。 。 来る。 used[i - 1] == true は、再帰の次のレベルに入り、次の番号に進むことを示し、分岐上にあります。

详细题解过程参考:40. 组合总和 II - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/combination-sum-ii/solutions/857552/dai-ma-sui-xiang-lu-dai-ni-xue-tou-hui-s-ig29/

代码

class Solution {
private:
    vector<int> path;
    vector<vector<int>> res;
public:
    void backing(vector<int>& candidates,int target,int startIndex,int curSum,vector<bool>& used)
    {
        if(curSum>target) return;
        if(curSum==target)
        {
            res.push_back(path);
            return;
        }

        for(int i=startIndex;i<candidates.size() && curSum+candidates[i]<=target;i++)
        {
            if(i>0 && candidates[i-1]==candidates[i] && used[i-1]==false)
            {
                continue;
            }
            else
            {
                curSum+=candidates[i];
                used[i]=true;
                path.push_back(candidates[i]);
                backing(candidates,target,i+1,curSum,used);
                path.pop_back();
                curSum-=candidates[i];
                used[i]=false;
            }
        }
    }
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        sort(candidates.begin(),candidates.end());
        vector<bool> used(candidates.size(),0);
        backing(candidates,target,0,0,used);
        return res;
    }
};

おすすめ

転載: blog.csdn.net/qq_58158950/article/details/134759966