Generate All Combinations Sum K in DSA C++ - Time & Space Complexity
We want to understand how the time needed to find all combinations that add up to a target number grows as the input size changes.
How does the number of combinations affect the work done?
Analyze the time complexity of the following code snippet.
void backtrack(int start, int k, int target, vector<int>& combination, vector<vector<int>>& result, vector<int>& candidates) {
if (target == 0 && combination.size() == k) {
result.push_back(combination);
return;
}
if (target < 0 || combination.size() > k) return;
for (int i = start; i < candidates.size(); i++) {
combination.push_back(candidates[i]);
backtrack(i + 1, k, target - candidates[i], combination, result, candidates);
combination.pop_back();
}
}
This code finds all unique combinations of numbers from the candidates list that sum to the target with exactly k elements.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive calls exploring combinations by looping through candidates.
- How many times: Potentially explores many subsets, branching at each candidate choice.
As input size grows, the number of possible combinations grows quickly because the code tries many subsets.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | Thousands of recursive calls |
| 20 | Millions of recursive calls |
| 30 | Billions of recursive calls |
Pattern observation: The work grows very fast, roughly like combinations of n items taken k at a time.
Time Complexity: O(C(n, k) * k)
This means the time needed grows roughly with the number of combinations of n items taken k at a time, multiplied by k for copying combinations.
[X] Wrong: "The code runs in linear time because it just loops through the candidates once."
[OK] Correct: The loop is inside a recursive call, so it repeats many times exploring different combinations, causing exponential growth.
Understanding this helps you explain how recursive backtracking explores many possibilities and why some problems need exponential time, which is a common topic in interviews.
"What if we allowed repeated use of the same candidate? How would the time complexity change?"
Practice
Generate All Combinations Sum K problem?Solution
Step 1: Understand the problem goal
The problem asks to find all unique sets of numbers that add up exactly to a given sum K.Step 2: Differentiate from other tasks
Sorting, finding max, or counting elements do not involve finding combinations that sum to K.Final Answer:
Find all unique combinations of numbers that add up to a target sum K -> Option BQuick Check:
Goal = Find combinations summing to K [OK]
- Confusing sum with sorting
- Looking for max instead of combinations
- Counting elements instead of combinations
candidates?Solution
Step 1: Check parameter passing and types
void findCombinations(int index, int target, vector<int>& candidates, vector<int>& current, vector& result) uses references for vectors to avoid copying and includes all needed parameters: index, target, candidates, current combination, and result container.Step 2: Identify correct return type and parameters
void findCombinations(int index, int target, vector<int>& candidates, vector<int>& current, vector& result) returns void because it modifies result by reference. Other options either return wrong types or pass vectors by value causing inefficiency.Final Answer:
void findCombinations(int index, int target, vector<int>& candidates, vector<int>& current, vector& result) -> Option AQuick Check:
Correct signature uses references and void return [OK]
- Passing vectors by value causing slow code
- Wrong return type for recursive helper
- Missing index parameter to track position
vector<int> candidates = {1, 2, 3};
vector result;
vector<int> current;
findCombinations(0, 5, candidates, current, result);
for (auto &comb : result) {
for (int num : comb) cout << num << ' ';
cout << '\n';
}Solution
Step 1: Understand combinations summing to 5
Possible combinations using {1,2,3} that sum to 5 include: - 1+1+1+1+1 - 1+1+1+2 - 1+1+3 - 1+2+2 - 2+3Step 2: Verify output matches these combinations
1 1 1 1 1 1 1 1 2 1 1 3 1 2 2 2 3 lists all these combinations correctly, each on a new line, matching expected output.Final Answer:
1 1 1 1 1 1 1 1 2 1 1 3 1 2 2 2 3 -> Option DQuick Check:
All valid combos summing to 5 listed [OK]
- Missing some valid combinations
- Including combinations that exceed sum
- Printing duplicates or unordered results
void findCombinations(int index, int target, vector<int>& candidates, vector<int>& current, vector& result) {
if (target == 0) {
result.push_back(current);
return;
}
for (int i = index; i < candidates.size(); i++) {
if (candidates[i] <= target) {
current.push_back(candidates[i]);
findCombinations(i + 1, target - candidates[i], candidates, current, result);
current.pop_back();
}
}
}Solution
Step 1: Analyze recursive call for repeated elements
Using 'i + 1' moves to next candidate, disallowing reuse of the same element multiple times.Step 2: Correct recursive call to allow repeats
Changing recursive call to use 'i' allows the same element to be chosen multiple times, which is needed for combinations sum problems allowing repeats.Final Answer:
The recursive call should use 'i' instead of 'i + 1' to allow repeated elements -> Option AQuick Check:
Use 'i' to allow repeats [OK]
- Incrementing index disallows repeated elements
- Wrong base case condition
- Incorrect return type for recursive helper
Solution
Step 1: Identify valid combinations summing to 7
From candidates {2,3,6,7}, valid combinations with unlimited repeats are: - [7] - [2, 2, 3] (2+2+3=7)Step 2: Check options for correctness
[[7], [2, 2, 3]] lists these exact combinations. Others include invalid numbers like 1 or 5 which are not in candidates.Final Answer:
[[7], [2, 2, 3]] -> Option CQuick Check:
Only valid combos from candidates listed [OK]
- Including numbers not in candidates
- Ignoring unlimited repeats
- Missing valid combinations
Ready to prove it?
Pass the test and this pattern moves unknown
