LeetCode - Medium - 40. Combination Sum II

小灰灰 2023-01-05 12:57 221阅读 0赞

Topic

  • Array
  • Backtracking

Description

https://leetcode.com/problems/combination-sum-ii/

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

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

Note: The solution set must not contain duplicate combinations.

Example 1:

  1. Input: candidates = [10,1,2,7,6,1,5], target = 8
  2. Output:
  3. [
  4. [1,1,6],
  5. [1,2,5],
  6. [1,7],
  7. [2,6]
  8. ]

Example 2:

  1. Input: candidates = [2,5,2,1,2], target = 5
  2. Output:
  3. [
  4. [1,2,2],
  5. [5]
  6. ]

Constraints:

  • 1 <= candidates.length <= 100
  • 1 <= candidates[i] <= 50
  • 1 <= target <= 30

Analysis

回溯算法:求组合总和(三)

Submission

  1. import java.util.ArrayList;
  2. import java.util.Arrays;
  3. import java.util.List;
  4. public class CombinationSumII {
  5. // 版本一:公众号“代码随想录”的
  6. public List<List<Integer>> combinationSum2(int[] candidates, int target) {
  7. List<List<Integer>> result = new ArrayList<>();
  8. List<Integer> path = new ArrayList<>();
  9. Arrays.sort(candidates);
  10. boolean[] used = new boolean[candidates.length];
  11. backtracking(path, candidates, target, used, 0, 0, result);
  12. return result;
  13. }
  14. private void backtracking(List<Integer> path, int[] candidates, int target, //
  15. boolean[] used, int sum, int startIndex, List<List<Integer>> result) {
  16. if (target == sum) {
  17. result.add(new ArrayList<>(path));
  18. return;
  19. }
  20. for (int i = startIndex; i < candidates.length && sum + candidates[i] <= target; i++) {
  21. if (i > 0 && candidates[i - 1] == candidates[i] && used[i - 1] == false)
  22. continue;
  23. sum += candidates[i];
  24. path.add(candidates[i]);
  25. used[i] = true;
  26. backtracking(path, candidates, target, used, sum, i + 1, result);
  27. sum -= candidates[i];
  28. path.remove(path.size() - 1);
  29. used[i] = false;
  30. }
  31. }
  32. // 版本二,跟版本一相比,没有sum,used变量
  33. public List<List<Integer>> combinationSum2_(int[] candidates, int target) {
  34. List<List<Integer>> res = new ArrayList<List<Integer>>();
  35. List<Integer> path = new ArrayList<Integer>();
  36. Arrays.sort(candidates);
  37. backtracking_(candidates, 0, target, path, res);
  38. return res;
  39. }
  40. private void backtracking_(int[] candidates, int startIndex, int target, List<Integer> path,
  41. List<List<Integer>> res) {
  42. if (target == 0) {
  43. res.add(new ArrayList<>(path));
  44. return;
  45. }
  46. for (int i = startIndex; i < candidates.length && target >= candidates[i]; i++) {
  47. if (i > startIndex && candidates[i] == candidates[i - 1])
  48. continue;
  49. path.add(candidates[i]);
  50. backtracking_(candidates, i + 1, target - candidates[i], path, res);
  51. path.remove(path.size() - 1);
  52. }
  53. }
  54. // 版本三,将版本一的used剔除掉,以及backtracking__方法体的 `i > 0 &&` 改为 `i > startIndex &&`
  55. public List<List<Integer>> combinationSum2__(int[] candidates, int target) {
  56. List<List<Integer>> result = new ArrayList<>();
  57. List<Integer> path = new ArrayList<>();
  58. Arrays.sort(candidates);
  59. backtracking__(path, candidates, target, 0, 0, result);
  60. return result;
  61. }
  62. private void backtracking__(List<Integer> path, int[] candidates, int target, //
  63. int sum, int startIndex, List<List<Integer>> result) {
  64. if (target == sum) {
  65. result.add(new ArrayList<>(path));
  66. return;
  67. }
  68. for (int i = startIndex; i < candidates.length && sum + candidates[i] <= target; i++) {
  69. if (i > startIndex && candidates[i - 1] == candidates[i])
  70. continue;
  71. sum += candidates[i];
  72. path.add(candidates[i]);
  73. backtracking__(path, candidates, target, sum, i + 1, result);
  74. sum -= candidates[i];
  75. path.remove(path.size() - 1);
  76. }
  77. }
  78. }

Test

  1. import static org.junit.Assert.*;
  2. import java.util.Arrays;
  3. import org.hamcrest.collection.IsIterableContainingInAnyOrder;
  4. import org.junit.Test;
  5. public class CombinationSumIITest {
  6. @Test
  7. @SuppressWarnings("unchecked")
  8. public void test() {
  9. CombinationSumII obj = new CombinationSumII();
  10. assertThat(obj.combinationSum2(new int[] { 10, 1, 2, 7, 6, 1, 5 }, 8), //
  11. IsIterableContainingInAnyOrder.containsInAnyOrder(Arrays.asList(1, 1, 6), Arrays.asList(1, 2, 5), //
  12. Arrays.asList(1, 7), Arrays.asList(2, 6)));
  13. assertThat(obj.combinationSum2(new int[] { 2, 5, 2, 1, 2 }, 5), //
  14. IsIterableContainingInAnyOrder.containsInAnyOrder(Arrays.asList(1, 2, 2), Arrays.asList(5)));
  15. }
  16. @Test
  17. @SuppressWarnings("unchecked")
  18. public void test2() {
  19. CombinationSumII obj = new CombinationSumII();
  20. assertThat(obj.combinationSum2_(new int[] { 10, 1, 2, 7, 6, 1, 5 }, 8), //
  21. IsIterableContainingInAnyOrder.containsInAnyOrder(Arrays.asList(1, 1, 6), Arrays.asList(1, 2, 5), //
  22. Arrays.asList(1, 7), Arrays.asList(2, 6)));
  23. assertThat(obj.combinationSum2_(new int[] { 2, 5, 2, 1, 2 }, 5), //
  24. IsIterableContainingInAnyOrder.containsInAnyOrder(Arrays.asList(1, 2, 2), Arrays.asList(5)));
  25. assertThat(obj.combinationSum2_(new int[] { 1, 1, 1}, 3), //
  26. IsIterableContainingInAnyOrder.containsInAnyOrder(Arrays.asList(1, 1, 1)));
  27. }
  28. @Test
  29. @SuppressWarnings("unchecked")
  30. public void test3() {
  31. CombinationSumII obj = new CombinationSumII();
  32. assertThat(obj.combinationSum2__(new int[] { 10, 1, 2, 7, 6, 1, 5 }, 8), //
  33. IsIterableContainingInAnyOrder.containsInAnyOrder(Arrays.asList(1, 1, 6), Arrays.asList(1, 2, 5), //
  34. Arrays.asList(1, 7), Arrays.asList(2, 6)));
  35. assertThat(obj.combinationSum2__(new int[] { 2, 5, 2, 1, 2 }, 5), //
  36. IsIterableContainingInAnyOrder.containsInAnyOrder(Arrays.asList(1, 2, 2), Arrays.asList(5)));
  37. assertThat(obj.combinationSum2__(new int[] { 1, 1, 1}, 3), //
  38. IsIterableContainingInAnyOrder.containsInAnyOrder(Arrays.asList(1, 1, 1)));
  39. }
  40. }

发表评论

表情:
评论列表 (有 0 条评论,221人围观)

还没有评论,来说两句吧...

相关阅读