Generate All Combinations Sum K in DSA Go - Time & Space Complexity
We want to understand how the time needed to find all combinations that add up to a target grows as the input changes.
How does the number of combinations affect the work done?
Analyze the time complexity of the following code snippet.
func combinationSumK(nums []int, k int) [][]int {
var res [][]int
var comb []int
var backtrack func(start, target int)
backtrack = func(start, target int) {
if target == 0 {
temp := make([]int, len(comb))
copy(temp, comb)
res = append(res, temp)
return
}
for i := start; i < len(nums); i++ {
if nums[i] > target {
continue
}
comb = append(comb, nums[i])
backtrack(i+1, target-nums[i])
comb = comb[:len(comb)-1]
}
}
backtrack(0, k)
return res
}
This code finds all unique combinations of numbers from the list that add up to k, using backtracking.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive backtracking calls exploring combinations.
- How many times: Potentially explores all subsets of nums, which can be up to 2^n combinations.
As the input list grows, the number of possible combinations grows very fast.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | Up to 2^10 = 1,024 combinations explored |
| 20 | Up to 2^20 = 1,048,576 combinations explored |
| 30 | Up to 2^30 = 1,073,741,824 combinations explored |
Pattern observation: The work doubles roughly with each additional element, growing exponentially.
Time Complexity: O(2^n * n)
This means the time grows exponentially with input size because it explores many subsets, and copying combinations takes extra time.
[X] Wrong: "The algorithm runs in linear time because it just loops through the list once."
[OK] Correct: The code uses recursion to explore many subsets, not just one pass, so the work grows much faster than linear.
Understanding this exponential growth helps you explain why some problems need careful pruning or different approaches, a key skill in interviews.
"What if we allowed repeated use of the same number in combinations? How would the time complexity change?"
Practice
Solution
Step 1: Understand the problem goal
The problem asks to find all unique sets of numbers that add exactly to the target sum K.Step 2: Clarify what combinations mean
Combinations mean groups of numbers where order does not matter, and each number can be used once or multiple times depending on problem rules.Final Answer:
All unique combinations of numbers that add up to K -> Option AQuick Check:
Combinations sum K = unique sets adding to K [OK]
- Confusing combinations with permutations
- Looking for a single sum instead of all combinations
- Ignoring the target sum K
Solution
Step 1: Identify input parameters
The function should take a slice of integers and a target integer sum.Step 2: Identify return type
It should return a slice of slices of integers, representing all combinations.Final Answer:
func combinationSum(nums []int, target int) [][]int -> Option DQuick Check:
Input slice and target int, output slice of int slices [OK]
- Swapping parameter types
- Returning a single slice instead of slice of slices
- Returning an int instead of combinations
func main() {
nums := []int{2, 3, 6, 7}
target := 7
result := combinationSum(nums, target)
fmt.Println(result)
}
func combinationSum(nums []int, target int) [][]int {
var res [][]int
var backtrack func(start, target int, path []int)
backtrack = func(start, target int, path []int) {
if target == 0 {
temp := make([]int, len(path))
copy(temp, path)
res = append(res, temp)
return
}
for i := start; i < len(nums); i++ {
if nums[i] > target {
continue
}
backtrack(i, target-nums[i], append(path, nums[i]))
}
}
backtrack(0, target, []int{})
return res
}Solution
Step 1: Understand backtracking logic
The function tries combinations starting from each index, allowing reuse of numbers, and collects paths summing to target.Step 2: Trace combinations for target 7
Possible sums are [2,2,2,3] and [7] because 2+2+2+3=9 is incorrect, so check carefully: 2+2+2+3=9 (too big), so that is invalid. The actual combinations are [2,2,3] (2+2+3=7) and [7].Step 3: Verify options
[[2 2 2 3] [7]] shows [2 2 2 3] which sums to 9, invalid. [[2 2 3] [7]] shows [2 2 3] and [7], which is correct.Final Answer:
[[2 2 3] [7]] -> Option AQuick Check:
Backtracking finds [2 2 3] and [7] sums [OK]
- Including invalid sums like [2 3 6]
- Ignoring reuse of numbers
- Confusing order of elements
func combinationSum(nums []int, target int) [][]int {
var res [][]int
var backtrack func(start, target int, path []int)
backtrack = func(start, target int, path []int) {
if target == 0 {
res = append(res, path)
return
}
for i := start; i < len(nums); i++ {
if nums[i] > target {
continue
}
backtrack(i, target-nums[i], append(path, nums[i]))
}
}
backtrack(0, target, []int{})
return res
}Solution
Step 1: Check how path is appended to result
Appending path directly stores the reference, causing all results to point to the same underlying array.Step 2: Fix by copying path before appending
Make a copy of path slice before appending to res to avoid shared references.Final Answer:
Appending path directly causes shared slice reference issues -> Option CQuick Check:
Copy path before append to avoid shared slice bugs [OK]
- Appending slice references directly
- Incorrect loop start index
- Wrong base case condition
Solution
Step 1: Sort the input list
Sorting helps group duplicates together so they can be skipped during recursion.Step 2: Skip duplicates in recursion
When iterating, skip numbers equal to the previous one at the same recursion level to avoid duplicate combinations.Final Answer:
Sort the list and skip duplicate numbers during recursion -> Option BQuick Check:
Sorting + skipping duplicates = unique combinations [OK]
- Filtering duplicates after generating all combinations
- Not sorting input before recursion
- Changing target incorrectly
Ready to prove it?
Pass the test and this pattern moves unknown
