39.数组总和40.数组总和

79 阅读1分钟

39.数组总和(给定无重复组合)

  • 所有数字(包括 target)都是正整数。
  • 解集不能包含重复的组合。
class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(candidates);
        back(result, new ArrayList<>(), candidates, target, 0, 0);
        return result;
    }
    public void back(List<List<Integer>> result, List<Integer> path, int[] candidates,int target, int sum, int idx){
        if(sum == target){
            result.add(new ArrayList<>(path));
            return;
        }
        for (int i = idx; i < candidates.length; i++){
            if (sum + candidates[i] > target) break;
            path.add(candidates[i]);
            back(result, path, candidates, target, sum + candidates[i], i);
            path.remove(path.size() - 1); 
        }
    }
}

40.数组总和(给定组合可能重复)

每个数字在每个组合中只能使用一次。

class Solution {//超时解法
    List<List<Integer>> result = new ArrayList<>();
    LinkedList<Integer> path = new LinkedList<>();
    int sum = 0;
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates);
        back(candidates, target, 0);
        return result;
    }
    private void back( int[] candidates, int target, int start ){
        if(sum == target){
            result.add(new ArrayList(path));
            return;
        }
        for(int i = start; i < candidates.length && candidates[i] <= target; i++){
            //每层元素不重复->组合不重复
            if(i > start && candidates[i] == candidates[i-1]) continue;
            sum += candidates[i];
            path.add(candidates[i]);
            //内循环
            back(candidates, target, i + 1);
            sum -= path.getLast();
            path.removeLast();
        }
    }
}
class Solution {//不超时
  LinkedList<Integer> path = new LinkedList<>();
  List<List<Integer>> ans = new ArrayList<>();
  boolean[] used;
  int sum = 0;

  public List<List<Integer>> combinationSum2(int[] candidates, int target) {
    used = new boolean[candidates.length];
    // 加标志数组,用来辅助判断同层节点是否已经遍历
    Arrays.fill(used, false);
    // 为了将重复的数字都放到一起,所以先进行排序
    Arrays.sort(candidates);
    backTracking(candidates, target, 0);
    return ans;
  }

  private void backTracking(int[] candidates, int target, int startIndex) {
    if (sum == target) {
      ans.add(new ArrayList(path));
    }
    for (int i = startIndex; i < candidates.length; i++) {
      if (sum + candidates[i] > target) {
        break;
      }
      // 出现重复节点,同层的第一个节点已经被访问过,所以直接跳过
      if (i > 0 && candidates[i] == candidates[i - 1] && !used[i - 1]) {
        continue;
      }
      used[i] = true;
      sum += candidates[i];
      path.add(candidates[i]);
      // 每个节点仅能选择一次,所以从下一位开始
      backTracking(candidates, target, i + 1);
      used[i] = false;
      sum -= candidates[i];
      path.removeLast();
    }
  }
}