40. 组合总和 II

206 阅读1分钟

题目介绍

力扣40题:leetcode-cn.com/problems/co…

image.png

回溯

该题目是[39. 组合总和]的变形,此时数组candidates中包含有相同的元素,这也需要考虑去重,这里的去重跟[47. 全排列 II]一样,首先将数组candidates进行排序,然后利用一个数组来标识当前节点的访问情况,如果当前元素跟上一个元素相同的,并且上一个元素还没有被访问过,则跳过当前节点。

//用于去重
if(i > 0 && candidates[i-1] == candidates[i] && !visited[i - 1]) {
    continue;
}

完整代码如下:

class Solution {
    private List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<Integer> path = new ArrayList<>();
        //用于去重
        boolean[] visited = new boolean[candidates.length];
        //排序,方便后面去重
        Arrays.sort(candidates);
        backTrack(candidates, target, 0, path, 0, visited);
        return res;
    }

    public void backTrack(int[] candidates, int target, int start, List<Integer> path, int curCount, boolean[] visited) {
        //满足条件
        if(curCount == target) {
            res.add(new ArrayList<Integer>(path));
        }
        // 注意 i 从 start 开始递增
        for (int i = start; i < candidates.length; i++) {
            if(curCount + candidates[i] > target) {
                continue;
            }
            //用于去重
            if(i > 0 && candidates[i-1] == candidates[i] && !visited[i - 1]) {
                continue;
            }
            // 做选择
            path.add(candidates[i]);
            curCount += candidates[i];
            visited[i] = true;
            //递归
            backTrack(candidates, target, i + 1, path, curCount, visited);
            // 撤销选择
            path.remove(path.size() - 1);
            curCount -= candidates[i];
            visited[i] = false;
        }
    }
}