【算法27天:Day27】第七章回溯算法 LeetCode 组合总和II(40)

71 阅读1分钟

题目二:

image.png

解法一:(回溯)

解题思路:这道题,主要就是要去除重复的结果组合,参考代码随想录

这个题的“去重”,主要是同一树层维度上的去重,而不是同一树枝维度上的去重。

var combinationSum2 = function(candidates, target) {
    const res = []; path = [], len = candidates.length;
    candidates.sort((a,b)=>a-b);
    backtracking(0, 0);
    return res;
    function backtracking(sum, startIndex) {
        if (sum === target) {
            res.push(Array.from(path));
            return;
        }
        for(let i = startIndex; i < len; i++) {
            const n = candidates[i];
            if(i > startIndex && candidates[i] === candidates[i-1]){
              //若当前元素和前一个元素相等
              //则本次循环结束,防止出现重复组合
              continue;
            }
            //如果当前元素值大于目标值-总和的值
            //由于数组已排序,那么该元素之后的元素必定不满足条件
            //直接终止当前层的递归
            if(n > target - sum) break;
            path.push(n);
            sum += n;
            backtracking(sum, i + 1);
            path.pop();
            sum -= n;
        }
    }
};

但其实自己写的代码,加上一行代码就可以了。

if (i > startIndex && candidates[i] === candidates[i - 1]) continue

完整代码:

var combinationSum2 = function(candidates, target) {
    let result = []
    let path = []
    candidates.sort((a, b) => a - b)
    const backtracking = function(sum, startIndex) {
        if (sum > target) return 
        if (sum === target) {
            result.push([...path])
            return 
        }
        for (let i = startIndex; i < candidates.length; i++) {
            if (i > startIndex && candidates[i] === candidates[i - 1]) continue
            path.push(candidates[i])
            sum += candidates[i]
            backtracking(sum, i + 1)
            path.pop()
            sum -= candidates[i]
        }
    }
    backtracking(0, 0)
    return result
};

解法二:(used)

var combinationSum2 = function(candidates, target) {
    let res = [];
    let path = [];
    let total = 0;
    const len = candidates.length;
    candidates.sort((a, b) => a - b);
    let used = new Array(len).fill(false);
    const backtracking = (startIndex) => {
        if (total === target) {
            res.push([...path]);
            return;
        }
        for(let i = startIndex; i < len && total < target; i++) {
            const cur = candidates[i];
            if (cur > target - total || (i > 0 && cur === candidates[i - 1] && !used[i - 1])) continue;
            path.push(cur);
            total += cur;
            used[i] = true;
            backtracking(i + 1);
            path.pop();
            total -= cur;
            used[i] = false;
        }
    }
    backtracking(0);
    return res;
};