7.5组合总和②(LC40-M)

7.5组合总和②(LC40-M)_第1张图片7.5组合总和②(LC40-M)_第2张图片

算法:

相比于上一题,数组candidates有重复元素,而要求不能有重复的组合,所以相对于39.组合总和 (opens new window)难度提升了不少。

如何去重?

先把candidates排序,让重复的元素都在一起

单层递归时,

 if ( i > startindex && candidates[i] == candidates[i - 1] ) {
        continue;
      }

调试过程:

class Solution {
//全局变量path和result
    List> result = new LinkedList<>();
    List path = new LinkedList<>();
    public List> combinationSum2(int[] candidates, int target) {
//`int[] candidates` 表示一个整数数组,可以包含多个整数元素。你可以通过`candidates[0]`、`candidates[1]`等方式访问数组中的不同元素。
//int target` 则表示一个单独的整数变量,只能存储一个整数值。
    if (candidates == null) return result;
     Arrays.sort(candidates);
     backtracking(candidates, target, 0, 0);
     return result;
    }
    void backtracking(int[] candidates, int target, int sum, int startindex){
    //确定终止条件
    if (sum > target) return;
    if (sum == target) {
        result.add(new LinkedList(path));
        return;
    }
    //单层递归逻辑
    for (int i = startindex; i < candidates.length && sum <= target; i++){
        if (i > startindex && candidates[i] == candidates[i-1]) continue;
        path.add(candidates[i]);
        sum += candidates[i];
        backtracking(candidates, target, sum, i);
        //回溯
        sum -= candidates[i];
        path.removeLast();
    }
    }
}

7.5组合总和②(LC40-M)_第3张图片

原因:没去重

单层递归中,应该改成i+1了

backtracking(candidates, target, sum, i+1);

正确代码:

class Solution {
//全局变量path和result
    List> result = new LinkedList<>();
    List path = new LinkedList<>();
    public List> combinationSum2(int[] candidates, int target) {
//`int[] candidates` 表示一个整数数组,可以包含多个整数元素。你可以通过`candidates[0]`、`candidates[1]`等方式访问数组中的不同元素。
//int target` 则表示一个单独的整数变量,只能存储一个整数值。
    if (candidates == null) return result;
//排序
     Arrays.sort(candidates);
     backtracking(candidates, target, 0, 0);
     return result;
    }
    void backtracking(int[] candidates, int target, int sum, int startindex){
    //确定终止条件
    if (sum > target) return;
    if (sum == target) {
        result.add(new LinkedList(path));
        return;
    }
    //单层递归逻辑
    for (int i = startindex; i < candidates.length && sum <= target; i++){
//去重
        if (i > startindex && candidates[i] == candidates[i-1]) continue;
        path.add(candidates[i]);
        sum += candidates[i];
        backtracking(candidates, target, sum, i+1);
        //回溯
        sum -= candidates[i];
        path.removeLast();
    }
    }
}

时间空间复杂度:

  • 时间复杂度: O(n * 2^n),注意这只是复杂度的上界,因为剪枝的存在,真实的时间复杂度远小于此
  • 空间复杂度: O(target)

你可能感兴趣的:(#,7.回溯,数据结构)