From be3bf77a66ee35d38da0430252e44caea9f6b727 Mon Sep 17 00:00:00 2001 From: Avaneeshakrishna <36323856+Avaneeshakrishna@users.noreply.github.com> Date: Fri, 10 Oct 2025 17:30:33 +0000 Subject: [PATCH 01/11] add CombinationSum and test --- .../backtracking/CombinationSum.java | 31 +++++++++++++++++++ .../backtracking/CombinationSumTest.java | 31 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 src/main/java/com/thealgorithms/backtracking/CombinationSum.java create mode 100644 src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java diff --git a/src/main/java/com/thealgorithms/backtracking/CombinationSum.java b/src/main/java/com/thealgorithms/backtracking/CombinationSum.java new file mode 100644 index 000000000000..540b4a34edf1 --- /dev/null +++ b/src/main/java/com/thealgorithms/backtracking/CombinationSum.java @@ -0,0 +1,31 @@ +package com.thealgorithms.backtracking; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** Backtracking: pick/not-pick with reuse of candidates. */ +public class CombinationSum { + + public static List> combinationSum(int[] candidates, int target) { + Arrays.sort(candidates); // helps pruning + List> res = new ArrayList<>(); + backtrack(candidates, target, 0, new ArrayList<>(), res); + return res; + // Note: result order is not guaranteed; compare sorted in tests if needed + } + + private static void backtrack(int[] nums, int remain, int start, List path, List> res) { + if (remain == 0) { + res.add(new ArrayList<>(path)); + return; + } + for (int i = start; i < nums.length; i++) { + int val = nums[i]; + if (val > remain) break; // prune + path.add(val); + backtrack(nums, remain - val, i, path, res); // i (reuse allowed) + path.remove(path.size() - 1); + } + } +} diff --git a/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java b/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java new file mode 100644 index 000000000000..554bfa740c4c --- /dev/null +++ b/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java @@ -0,0 +1,31 @@ +package com.thealgorithms.backtracking; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import org.junit.jupiter.api.Test; + +class CombinationSumTest { + + private static List> norm(List> x) { + List> y = new ArrayList<>(); + for (var p : x) { + var q = new ArrayList<>(p); + q.sort(Integer::compare); + y.add(q); + } + y.sort(Comparator., Integer>comparing(List::size) + .thenComparing(a -> a.toString())); + return y; + } + + @Test + void sample() { + int[] candidates = {2,3,6,7}; + int target = 7; + var expected = List.of(List.of(2,2,3), List.of(7)); + assertEquals(norm(expected), norm(CombinationSum.combinationSum(candidates, target))); + } +} From 79dc52b4da63557dc1ea1d6baee95689b2be45be Mon Sep 17 00:00:00 2001 From: Avaneeshakrishna <36323856+Avaneeshakrishna@users.noreply.github.com> Date: Fri, 10 Oct 2025 12:50:01 -0700 Subject: [PATCH 02/11] Format array and list literals in CombinationSumTest --- .../com/thealgorithms/backtracking/CombinationSumTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java b/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java index 554bfa740c4c..c848f7b191a5 100644 --- a/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java +++ b/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java @@ -23,9 +23,9 @@ private static List> norm(List> x) { @Test void sample() { - int[] candidates = {2,3,6,7}; + int[] candidates = {2, 3, 6, 7}; int target = 7; - var expected = List.of(List.of(2,2,3), List.of(7)); + var expected = List.of(List.of(2, 2, 3), List.of(7)); assertEquals(norm(expected), norm(CombinationSum.combinationSum(candidates, target))); } } From 66a27616fcf204fd63f1339fdfdc3f05189b0e36 Mon Sep 17 00:00:00 2001 From: Avaneeshakrishna <36323856+Avaneeshakrishna@users.noreply.github.com> Date: Fri, 10 Oct 2025 12:52:19 -0700 Subject: [PATCH 03/11] Fix sorting comparator in CombinationSumTest --- .../com/thealgorithms/backtracking/CombinationSumTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java b/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java index c848f7b191a5..252be630ac0e 100644 --- a/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java +++ b/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java @@ -16,8 +16,7 @@ private static List> norm(List> x) { q.sort(Integer::compare); y.add(q); } - y.sort(Comparator., Integer>comparing(List::size) - .thenComparing(a -> a.toString())); + y.sort(Comparator., Integer>comparing(List::size).thenComparing(a -> a.toString())); return y; } From 4e1cdd273352b92116fc06b2f7e7b548f02de739 Mon Sep 17 00:00:00 2001 From: Avaneeshakrishna <36323856+Avaneeshakrishna@users.noreply.github.com> Date: Fri, 10 Oct 2025 13:02:41 -0700 Subject: [PATCH 04/11] Refactor CombinationSum for better handling and clarity Updated combinationSum method to handle null or empty candidates and improved variable naming for clarity. --- .../backtracking/CombinationSum.java | 48 +++++++++++++------ 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/thealgorithms/backtracking/CombinationSum.java b/src/main/java/com/thealgorithms/backtracking/CombinationSum.java index 540b4a34edf1..7caf3c88e419 100644 --- a/src/main/java/com/thealgorithms/backtracking/CombinationSum.java +++ b/src/main/java/com/thealgorithms/backtracking/CombinationSum.java @@ -6,26 +6,44 @@ /** Backtracking: pick/not-pick with reuse of candidates. */ public class CombinationSum { + private CombinationSum() { + throw new UnsupportedOperationException("Utility class"); +} + + public static List> combinationSum(int[] candidates, int target) { + List> results = new ArrayList<>(); + if (candidates == null || candidates.length == 0) { + return results; + } - public static List> combinationSum(int[] candidates, int target) { - Arrays.sort(candidates); // helps pruning - List> res = new ArrayList<>(); - backtrack(candidates, target, 0, new ArrayList<>(), res); - return res; - // Note: result order is not guaranteed; compare sorted in tests if needed + // Sort to help with pruning duplicates and early termination + Arrays.sort(candidates); + backtrack(candidates, target, 0, new ArrayList<>(), results); + return results; } - private static void backtrack(int[] nums, int remain, int start, List path, List> res) { - if (remain == 0) { - res.add(new ArrayList<>(path)); + private static void backtrack(int[] candidates, int remaining, int start, + List combination, List> results) { + if (remaining == 0) { + // Found valid combination; add a copy + results.add(new ArrayList<>(combination)); return; } - for (int i = start; i < nums.length; i++) { - int val = nums[i]; - if (val > remain) break; // prune - path.add(val); - backtrack(nums, remain - val, i, path, res); // i (reuse allowed) - path.remove(path.size() - 1); + + for (int i = start; i < candidates.length; i++) { + int candidate = candidates[i]; + + // If candidate is greater than remaining target, further candidates (sorted) will also be too big + if (candidate > remaining) { + break; + } + + // include candidate + combination.add(candidate); + // Because we can reuse the same element, we pass i (not i + 1) + backtrack(candidates, remaining - candidate, i, combination, results); + // backtrack: remove last + combination.remove(combination.size() - 1); } } } From 1b12663277ff1310169a00b529301efce708f456 Mon Sep 17 00:00:00 2001 From: Avaneeshakrishna <36323856+Avaneeshakrishna@users.noreply.github.com> Date: Fri, 10 Oct 2025 13:10:01 -0700 Subject: [PATCH 05/11] Fix sorting comparator in CombinationSumTest --- .../java/com/thealgorithms/backtracking/CombinationSumTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java b/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java index 252be630ac0e..2d728485f645 100644 --- a/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java +++ b/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java @@ -16,7 +16,7 @@ private static List> norm(List> x) { q.sort(Integer::compare); y.add(q); } - y.sort(Comparator., Integer>comparing(List::size).thenComparing(a -> a.toString())); + y.sort(Comparator.comparingInt(List::size).thenComparing(Object::toString)); return y; } From 5c9015420963abce7b50cf8338ae186edeb579f3 Mon Sep 17 00:00:00 2001 From: Avaneeshakrishna <36323856+Avaneeshakrishna@users.noreply.github.com> Date: Fri, 10 Oct 2025 13:18:21 -0700 Subject: [PATCH 06/11] Update CombinationSumTest.java From 23fc7ef86400f776d8fde9d61e4252c3347d37a3 Mon Sep 17 00:00:00 2001 From: Avaneeshakrishna <36323856+Avaneeshakrishna@users.noreply.github.com> Date: Fri, 10 Oct 2025 13:20:52 -0700 Subject: [PATCH 07/11] Fix sorting comparator for list of integers --- .../java/com/thealgorithms/backtracking/CombinationSumTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java b/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java index 2d728485f645..70570d9ea509 100644 --- a/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java +++ b/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java @@ -16,7 +16,7 @@ private static List> norm(List> x) { q.sort(Integer::compare); y.add(q); } - y.sort(Comparator.comparingInt(List::size).thenComparing(Object::toString)); + y.sort(Comparator.>comparingInt(List::size).thenComparing(Object::toString)); return y; } From 543ab54e02b8767b6db39851aa185f6ec4061b58 Mon Sep 17 00:00:00 2001 From: Avaneeshakrishna <36323856+Avaneeshakrishna@users.noreply.github.com> Date: Fri, 10 Oct 2025 13:32:40 -0700 Subject: [PATCH 08/11] Fix formatting issues in CombinationSum class --- .../com/thealgorithms/backtracking/CombinationSum.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/thealgorithms/backtracking/CombinationSum.java b/src/main/java/com/thealgorithms/backtracking/CombinationSum.java index 7caf3c88e419..145a1bfbd7a1 100644 --- a/src/main/java/com/thealgorithms/backtracking/CombinationSum.java +++ b/src/main/java/com/thealgorithms/backtracking/CombinationSum.java @@ -7,10 +7,10 @@ /** Backtracking: pick/not-pick with reuse of candidates. */ public class CombinationSum { private CombinationSum() { - throw new UnsupportedOperationException("Utility class"); -} + throw new UnsupportedOperationException("Utility class"); + } - public static List> combinationSum(int[] candidates, int target) { + public static List> combinationSum(int[] candidates, int target) { List> results = new ArrayList<>(); if (candidates == null || candidates.length == 0) { return results; @@ -22,8 +22,7 @@ public static List> combinationSum(int[] candidates, int target) { return results; } - private static void backtrack(int[] candidates, int remaining, int start, - List combination, List> results) { + private static void backtrack(int[] candidates, int remaining, int start, List combination, List> results) { if (remaining == 0) { // Found valid combination; add a copy results.add(new ArrayList<>(combination)); From 08aafc569ecee9b98605b420e865334847adefe8 Mon Sep 17 00:00:00 2001 From: Avaneeshakrishna <36323856+Avaneeshakrishna@users.noreply.github.com> Date: Fri, 10 Oct 2025 13:38:23 -0700 Subject: [PATCH 09/11] Change CombinationSum class to final --- .../java/com/thealgorithms/backtracking/CombinationSum.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/backtracking/CombinationSum.java b/src/main/java/com/thealgorithms/backtracking/CombinationSum.java index 145a1bfbd7a1..09b99032bdc1 100644 --- a/src/main/java/com/thealgorithms/backtracking/CombinationSum.java +++ b/src/main/java/com/thealgorithms/backtracking/CombinationSum.java @@ -5,7 +5,7 @@ import java.util.List; /** Backtracking: pick/not-pick with reuse of candidates. */ -public class CombinationSum { +public final class CombinationSum { private CombinationSum() { throw new UnsupportedOperationException("Utility class"); } From 8238ad85bef0b5dd1074b74e444404e49c2d7725 Mon Sep 17 00:00:00 2001 From: Avaneeshakrishna <36323856+Avaneeshakrishna@users.noreply.github.com> Date: Fri, 10 Oct 2025 13:45:39 -0700 Subject: [PATCH 10/11] Refactor norm method to accept Iterable instead of List --- .../com/thealgorithms/backtracking/CombinationSumTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java b/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java index 70570d9ea509..3477cbab69c4 100644 --- a/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java +++ b/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java @@ -8,8 +8,8 @@ import org.junit.jupiter.api.Test; class CombinationSumTest { - - private static List> norm(List> x) { + + private static List> norm(Iterable> x) { List> y = new ArrayList<>(); for (var p : x) { var q = new ArrayList<>(p); From 3ff2e3b7ac286128bb0400542358cce4cc94c5e8 Mon Sep 17 00:00:00 2001 From: Avaneeshakrishna <36323856+Avaneeshakrishna@users.noreply.github.com> Date: Fri, 10 Oct 2025 13:53:32 -0700 Subject: [PATCH 11/11] Remove unnecessary whitespace in CombinationSumTest --- .../java/com/thealgorithms/backtracking/CombinationSumTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java b/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java index 3477cbab69c4..986c71acebe8 100644 --- a/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java +++ b/src/test/java/com/thealgorithms/backtracking/CombinationSumTest.java @@ -8,7 +8,6 @@ import org.junit.jupiter.api.Test; class CombinationSumTest { - private static List> norm(Iterable> x) { List> y = new ArrayList<>(); for (var p : x) {