[LeetCode40. 组合总和 II]回溯

  • 这里有陷阱就是提供数组会有重复元素,而输出的组合不能有重复,所以要在搜索的过程中就去掉重复组合。  

  • 组合问题可以抽象为树形结构,那么“使用过”在这个树形结构上是有两个维度的,一个维度是同一树枝上使用过,一个维度是同一树层上使用过。

  • 树枝上表示纵向的回溯,可以出现重复元素:[1, 1, 6]

  • 树层表示横向的遍历,不能出现重复元素:[1, 2, 5]、[1, 2, 5],否则就会出现重复的组合

  • 强调一下,树层去重的话,需要对数组排序!

  • 这里使用startIndex进行去重(也可以使用used数组)

  • 在同层遍历 i大于startIndex的情况下,如果当前元素和前一个元素相同,则跳过这个元素, i大于startIndex可以跳过树枝上的重复情况,只判断树层上的重复情况

class Solution {
    LinkedList<Integer> path = new LinkedList<>();
    List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates); // 先进行排序
        backtracking(candidates, target, 0, 0);
        return res;
    }

    public void backtracking (int[] candidates, int target, int sum, int startIndex) {
        if (sum == target) {
            res.add(new ArrayList<>(path));
            return;
        }
        // 这里仍然采用上一题的去重
        for (int i = startIndex; i < candidates.length && sum + candidates[i] <= target; i++) {
            // 要对同一树层使用过的元素进行跳过
            if (i > startIndex && candidates[i] == candidates[i - 1]) {
                continue;
            }
            path.add(candidates[i]);
            sum += candidates[i];
            backtracking(candidates, target, sum, i + 1);
            path.removeLast();
            sum -= candidates[i];
        }
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值