力扣40. 组合总和 II(java 回溯法)

Problem: 40. 组合总和 II

题目描述

在这里插入图片描述在这里插入图片描述

思路

在使用回溯之前我们首先可以明确该题目也是一种元素存在重复但不可复用的组合类型问题。而此题目可以参考下面一题的大体处理思路:

Problem: 90. 子集 II

具体的:

1.首先对给定的数组排序
2.我们要记录一个决策路径path,一个路径和pathSum,我们在回溯的过程中若当前的路劲和pathSum等于给定的target时我们将当前的决策路径添加到结果集和中并返回;若路径和pathSum在递归过程中大于了target则直接返回;
3.在回溯函数中我们每次循环开始穷举,起始位置(i)为当前的决策阶段(start),并判断若i > start && candidates[i] == candidates[i - 1]此处的candidates为回溯函数中的可选列表,则不递归达到去重的效果,最后恢复当前决策路径path与路径和pathSum

解题方法

1.定义二维结果集合result,决策路径path,路径和pathSum
2.对给定数组排序
3.编写调用回溯函数,初始决策阶段为0:

3.1当前的路劲和pathSum等于给定的target时我们将当前的决策路径添加到结果集和中并返回;若路径和pathSum在递归过程中大于了target则直接返回;
3.2for循环穷举,起始位置i为当前的决策阶段start,并判断若i > start && candidates[i] == candidates[i - 1],c则continue,不递归该分支
3.3每次将当前可选列表上的值添加到路径值pathSum,并递归调用,最后恢复当前决策路径,和路径和

复杂度

时间复杂度:

O ( n × 2 n ) O(n \times 2^n) O(n×2n)

空间复杂度:

O ( n ) O(n) O(n)

Code

class Solution {
    //Result list
    private List<List<Integer>> result = new ArrayList<>();
    //Decision path
    private List<Integer> path = new ArrayList<>();
    //Recode the sum of path
    private int pathSum = 0;

    /**
     * Gets all and a subset of the specified values
     *
     * @param candidates Specific list
     * @param target     target
     * @return List<List < Integer>>
     */
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates);
        backtrack(candidates, 0, target);
        return result;
    }

    /**
     * Solve for all subsets of specified values using backtracking
     *
     * @param candidates Optional list
     * @param start      Decision stage
     * @param target     target
     */
    private void backtrack(int[] candidates, int start, int target) {
        //End condition
        //if the pathSum equals the target
        if (pathSum == target) {
            result.add(new ArrayList<>(path));
            return;
        }
        //End condition
        //If the path bigger than target
        if (pathSum > target) {
            return;
        }
        for (int i = start; i < candidates.length; ++i) {
            if (i > start && candidates[i] == candidates[i - 1]) {
                continue;
            }
            path.add(candidates[i]);
            pathSum += candidates[i];
            backtrack(candidates, i + 1, target);
            //Recover the current Decision Path of path
            path.remove(path.size() - 1);
            pathSum -= candidates[i];
        }
    }
}
  • 16
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值