From c8d5bd5b5d66461da2e77cf2e0aecc598589d986 Mon Sep 17 00:00:00 2001 From: Sanjoli Singh Date: Wed, 22 Jul 2026 13:14:51 -0500 Subject: [PATCH] Completed Backtracking 1 --- CombinationSum.java | 34 ++++++++++++++++++++++++++++ ExpressionAddOperator.java | 46 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 CombinationSum.java create mode 100644 ExpressionAddOperator.java diff --git a/CombinationSum.java b/CombinationSum.java new file mode 100644 index 00000000..98210b09 --- /dev/null +++ b/CombinationSum.java @@ -0,0 +1,34 @@ +class Solution { + /* + TC = O(N^M), where M is the target/smallest number and N is the total numbers + SC - O(M) - recursive stack, where M is the target/smallest number + Maintain a path representing the current combination. + If target == 0, add the current path to the result. + If target < 0, stop exploring that branch. + Iterate from the current pivot index to avoid duplicate combinations. + Recursively call with the same index (i) so the current number can be reused unlimited times. + After recursion, remove the last element (backtrack) and try the next candidate. + */ + List> result; + public List> combinationSum(int[] candidates, int target) { + this.result = new ArrayList<>(); + helper(candidates, target, new ArrayList<>(), 0); + return result; + } + + private void helper(int[] candidates, int target, List path, int pivot) { + if (target < 0) { + return; + } + if (target == 0) { + result.add(new ArrayList<>(path)); + return; + } + + for (int i = pivot; i < candidates.length; i++) { + path.add(candidates[i]); + helper(candidates, target - candidates[i], path, i); + path.remove(path.size() - 1); + } + } +} \ No newline at end of file diff --git a/ExpressionAddOperator.java b/ExpressionAddOperator.java new file mode 100644 index 00000000..a3a611d8 --- /dev/null +++ b/ExpressionAddOperator.java @@ -0,0 +1,46 @@ +class Solution { + /* + TC - O(4^N), N is the input length and 4 is the possible number of combinations we can choose from + SC - O(N), N is the input length + + This solution uses backtracking (DFS) to generate all possible expressions by inserting +, -, and * operators between digits of the input string. + The helper function recursively chooses the next number from the remaining digits. + calc keeps the current evaluated value of the expression. + tail stores the last operand value, which helps correctly evaluate multiplication due to operator precedence. + When adding multiplication: calc - tail + tail * curr removes the previous operand and replaces it with the multiplied result. + We skip numbers with leading zeros (like "05") to avoid invalid expressions. + When all digits are processed, if calc == target, the expression is added to the result list. + */ + List result; + public List addOperators(String num, int target) { + this.result = new ArrayList<>(); + helper(num, target, 0, 0l, 0l, new StringBuilder()); + return result; + } + + private void helper(String num, int target, int pivot, long calc, long tail, StringBuilder path) { + if (pivot == num.length()) { + if (calc == target) { + result.add(path.toString()); + } + } + + int len = path.length(); + + for (int i = pivot; i < num.length(); i++) { + if (pivot != i && num.charAt(pivot) == '0') continue; + long curr = Long.parseLong(num.substring(pivot, i + 1)); + if (pivot == 0) { + helper(num, target, i + 1, curr, curr, path.append(curr)); + path.setLength(len); + } else { + helper(num, target, i + 1, calc + curr, curr, path.append("+" + curr)); + path.setLength(len); + helper(num, target, i + 1, calc - curr, -curr, path.append("-" + curr)); + path.setLength(len); + helper(num, target, i + 1, calc - tail + tail * curr, tail * curr, path.append("*" + curr)); + path.setLength(len); + } + } + } +} \ No newline at end of file