diff --git a/combinationsum.py b/combinationsum.py new file mode 100644 index 00000000..4f9e5c2e --- /dev/null +++ b/combinationsum.py @@ -0,0 +1,56 @@ +# approach: exhaustive recurssion(pick/skip) +# TC: O(2^(m+n)), branching at each step and unlimited reuse +# SC:O(T)(recurssion) + O(k*L) (resultant array) +from typing import List + + +class Solution: + def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: + def helper(candidates, target, i, path): + # base case + if target < 0 or i == len(candidates): + return + + if target == 0: + result.append(path[:]) + return + + # no choose + helper(candidates, target, i + 1, path) + + # choose + path.append(candidates[i]) + helper(candidates, target - candidates[i], i, path) + path.pop() + + result = [] + path = [] + helper(candidates, target, 0, path) + return result + + # Approach: For-loop based (pivot style) + # TC: O(2^(m+n)), branching at each step and unlimited reuse + # SC:O(T)(recurssion) + O(k*L) (resultant array) + def combinationSum_pivot( + self, candidates: List[int], target: int + ) -> List[List[int]]: + def helper2(candidates, target, pivot, path): + if target < 0: + return + if target == 0: + result2.append(path[:]) + return + for i in range(pivot, len(candidates)): + path.append(candidates[i]) + helper2(candidates, target - candidates[i], i, path) + path.pop() + + result2 = [] + helper2(candidates, target, 0, []) + return result2 + + +sol = Solution() +array = [2, 2, 3, 1, 6] +print(sol.combinationSum(array, 7)) +print(sol.combinationSum_pivot(array, 7)) diff --git a/expressionAddOperators.py b/expressionAddOperators.py new file mode 100644 index 00000000..44495276 --- /dev/null +++ b/expressionAddOperators.py @@ -0,0 +1,79 @@ +from typing import List + + +class Solution: + # Approach: String Concatenation Path + # TC: O(4^n), SC: O(n) + O(k) for recursion and result + + def addOperators(self, num: str, target: int) -> List[str]: + def helper(pivot, calc, tail, path): + if pivot == len(num): + if calc == target: + result.append(path) + return + + for i in range(pivot, len(num)): + if i > pivot and num[pivot] == "0": # skip leading zeros + break + + curr_str = num[pivot : i + 1] + curr = int(curr_str) + + if pivot == 0: + helper(i + 1, curr, curr, curr_str) + else: + helper(i + 1, calc + curr, curr, path + "+" + curr_str) + helper(i + 1, calc - curr, -curr, path + "-" + curr_str) + helper( + i + 1, + calc - tail + tail * curr, + tail * curr, + path + "*" + curr_str, + ) + + result = [] + helper(0, 0, 0, "") + return result + + # Alternate Approach: Backtracking using Path List + # TC: O(4^n), SC: O(n) + O(k) + def addOperatorsBacktrack(self, num: str, target: int) -> List[str]: + def helper(pivot, calc, tail, path): + if pivot == len(num): + if calc == target: + result.append("".join(path)) + return + + for i in range(pivot, len(num)): + if i > pivot and num[pivot] == "0": + break + + curr_str = num[pivot : i + 1] + curr = int(curr_str) + len_before = len(path) + + if pivot == 0: + path.append(curr_str) + helper(i + 1, curr, curr, path) + path[:] = path[:len_before] + else: + path.extend(["+", curr_str]) + helper(i + 1, calc + curr, curr, path) + path[:] = path[:len_before] + + path.extend(["-", curr_str]) + helper(i + 1, calc - curr, -curr, path) + path[:] = path[:len_before] + + path.extend(["*", curr_str]) + helper(i + 1, calc - tail + tail * curr, tail * curr, path) + path[:] = path[:len_before] + + result = [] + helper(0, 0, 0, []) + return result + + +sol = Solution() +print(sol.addOperators("123", 6)) +print(sol.addOperatorsBacktrack("123", 6))