Skip to content

Commit 5323084

Browse files
add CombinationSum and test (#6725)
* add CombinationSum and test * Format array and list literals in CombinationSumTest * Fix sorting comparator in CombinationSumTest * Refactor CombinationSum for better handling and clarity Updated combinationSum method to handle null or empty candidates and improved variable naming for clarity. * Fix sorting comparator in CombinationSumTest * Update CombinationSumTest.java * Fix sorting comparator for list of integers * Fix formatting issues in CombinationSum class * Change CombinationSum class to final * Refactor norm method to accept Iterable instead of List * Remove unnecessary whitespace in CombinationSumTest
1 parent 8c8527c commit 5323084

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.thealgorithms.backtracking;
2+
3+
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
import java.util.List;
6+
7+
/** Backtracking: pick/not-pick with reuse of candidates. */
8+
public final class CombinationSum {
9+
private CombinationSum() {
10+
throw new UnsupportedOperationException("Utility class");
11+
}
12+
13+
public static List<List<Integer>> combinationSum(int[] candidates, int target) {
14+
List<List<Integer>> results = new ArrayList<>();
15+
if (candidates == null || candidates.length == 0) {
16+
return results;
17+
}
18+
19+
// Sort to help with pruning duplicates and early termination
20+
Arrays.sort(candidates);
21+
backtrack(candidates, target, 0, new ArrayList<>(), results);
22+
return results;
23+
}
24+
25+
private static void backtrack(int[] candidates, int remaining, int start, List<Integer> combination, List<List<Integer>> results) {
26+
if (remaining == 0) {
27+
// Found valid combination; add a copy
28+
results.add(new ArrayList<>(combination));
29+
return;
30+
}
31+
32+
for (int i = start; i < candidates.length; i++) {
33+
int candidate = candidates[i];
34+
35+
// If candidate is greater than remaining target, further candidates (sorted) will also be too big
36+
if (candidate > remaining) {
37+
break;
38+
}
39+
40+
// include candidate
41+
combination.add(candidate);
42+
// Because we can reuse the same element, we pass i (not i + 1)
43+
backtrack(candidates, remaining - candidate, i, combination, results);
44+
// backtrack: remove last
45+
combination.remove(combination.size() - 1);
46+
}
47+
}
48+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.thealgorithms.backtracking;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
5+
import java.util.ArrayList;
6+
import java.util.Comparator;
7+
import java.util.List;
8+
import org.junit.jupiter.api.Test;
9+
10+
class CombinationSumTest {
11+
private static List<List<Integer>> norm(Iterable<List<Integer>> x) {
12+
List<List<Integer>> y = new ArrayList<>();
13+
for (var p : x) {
14+
var q = new ArrayList<>(p);
15+
q.sort(Integer::compare);
16+
y.add(q);
17+
}
18+
y.sort(Comparator.<List<Integer>>comparingInt(List::size).thenComparing(Object::toString));
19+
return y;
20+
}
21+
22+
@Test
23+
void sample() {
24+
int[] candidates = {2, 3, 6, 7};
25+
int target = 7;
26+
var expected = List.of(List.of(2, 2, 3), List.of(7));
27+
assertEquals(norm(expected), norm(CombinationSum.combinationSum(candidates, target)));
28+
}
29+
}

0 commit comments

Comments
 (0)