diff --git a/CombinationSum.swift b/CombinationSum.swift new file mode 100644 index 00000000..d4cf5ff5 --- /dev/null +++ b/CombinationSum.swift @@ -0,0 +1,143 @@ +// +// CombinationSum.swift +// DSA-Practice +// +// Created by Paridhi Malviya on 2/2/26. +// + +class CombinationSum { + func combinationSum(_ candidates: [Int], _ target: Int) -> [[Int]] { + var result = [[Int]]() + helper(candidates: candidates, idx: 0, target: target, path: [], result: &result) + return result + } + + //0-1 recursion + /* + time complexity - 2^(m + n) + space complexity - depth of recursion stack - (m+n) + */ + func helper(candidates: [Int], idx: Int, target: Int, path: [Int], result: inout [[Int]]) { + //base + if (target == 0) { + result.append(path) + return + } + if (idx == candidates.count || target < 0) { + return + } + + //logic + + //recurse + + //no choose + helper(candidates: candidates, idx: idx + 1, target: target, path: path, result: &result) + var path = path + path.append(candidates[idx]) + //choose + helper(candidates: candidates, idx: idx, target: target - candidates[idx], path: path, result: &result) + } +} + +class CombinationSumUsingForLoopBasedRecursion { + func combinationSum(_ candidates: [Int], _ target: Int) -> [[Int]] { + var result = [[Int]]() + getCombinations(candidates: candidates, start: 0, target: target, path: [], result: &result) + return result + } + + //for loop based recursion - time complexty - 2^(m+n) + /* + here width of the tree is more and height is lesser. Effectvely it's choose, not choose algorithm only. + Some places, for loop based recursions is beneficial because it's easier to reach solution. + case in point, permutation of string, combination of string + */ + func getCombinations(candidates: [Int], start: Int, target: Int, path: [Int], result: inout [[Int]]) { + //base + if (target == 0) { + result.append(path) + return + } + + if (target < 0) { + return + } + + //logic + var path = path + for i in start.. [[Int]] { + var result = [[Int]]() + getCombinationsWithDifferentArrangements(candidates: candidates, target: target, path: [],result: &result) + return result + } + + func getCombinationsWithDifferentArrangements(candidates: [Int], target: Int, path: [Int], result: inout [[Int]]) { + //base + if (target < 0) { + return + } + if (target == 0) { + result.append(path) + return + } + + //logic + var path = path + for i in 0.. [String] { + var result = [String]() + var path = [Character]() + helper(Array(num), start: 0, target, calculated: 0, tail: 0, path: path, result: &result) + return result + } + + func helper(_ numArr: [Character], start: Int, _ target: Int, calculated: Int, tail: Int, path: [Character], result: inout [String]) { + //the start pointer went out of bounds + if (start == numArr.count) { + if (calculated == target) { + result.append(String(path)) + } + return + } + //logic + for i in start.. [String] { + var result = [String]() + var path: [Character] = [] + helperB(Array(num), start: 0, target, calculated: 0, tail: 0, path: &path, result: &result) + return result + } + + func helperB(_ numArr: [Character], start: Int, _ target: Int, calculated: Int, tail: Int, path: inout [Character], result: inout [String]) { + //the start pointer went out of bounds + if (start == numArr.count) { + if (calculated == target) { + result.append(String(path)) + } + return + } + //logic + for i in start..