Combination Sum II

描述

Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.

Each number in C may only be used once in the combination.

Note:

  • All numbers (including target) will be positive integers.
  • Elements in a combination (a1,a2,…,aka_1, a_2, …, a_ka​1​​,a​2​​,…,a​k​​) must be in non-descending order. (ie, a1>a2>…>aka_1 > a_2 > … > a_ka​1​​>a​2​​>…>a​k​​).
  • The solution set must not contain duplicate combinations.
    For example, given candidate set 10,1,2,7,6,1,5 and target 8, A solution set is:
  1. [1, 7]
  2. [1, 2, 5]
  3. [2, 6]
  4. [1, 1, 6]

分析

代码

  1. // Combination Sum II
  2. // 时间复杂度O(n!),空间复杂度O(n)
  3. public class Solution {
  4. public List<List<Integer>> combinationSum2(int[] nums, int target) {
  5. Arrays.sort(nums); // 跟第 50 行配合,
  6. // 确保每个元素最多只用一次
  7. List<List<Integer>> result = new ArrayList<>();
  8. List<Integer> path = new ArrayList<>();
  9. dfs(nums, path, result, target, 0);
  10. return result;
  11. }
  12. // 使用nums[start, nums.size())之间的元素,能找到的所有可行解
  13. private static void dfs(int[] nums, List<Integer> path,
  14. List<List<Integer>> result, int gap, int start) {
  15. if (gap == 0) { // 找到一个合法解
  16. result.add(new ArrayList<>(path));
  17. return;
  18. }
  19. int previous = -1;
  20. for (int i = start; i < nums.length; i++) {
  21. // 如果上一轮循环已经使用了nums[i],则本次循环就不能再选nums[i],
  22. // 确保nums[i]最多只用一次
  23. if (previous == nums[i]) continue;
  24. if (gap < nums[i]) return; // 剪枝
  25. previous = nums[i];
  26. path.add(nums[i]);
  27. dfs(nums, path, result, gap - nums[i], i + 1);
  28. path.remove(path.size() - 1); // 恢复环境
  29. }
  30. }
  31. }

相关题目

原文: https://soulmachine.gitbooks.io/algorithm-essentials/content/java/dfs/combination-sum-ii.html