Skip to content

Commit 88547b3

Browse files
committed
Combination sum 2
1 parent 67de492 commit 88547b3

File tree

4 files changed

+148
-0
lines changed

4 files changed

+148
-0
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# 40. Combination Sum II
2+
3+
**Difficulty:** *Medium*
4+
**Category:** *Backtracking, Recursion*
5+
**Leetcode Link:** [Problem Link](https://leetcode.com/problems/combination-sum-ii/)
6+
7+
---
8+
9+
## 📝 Introduction
10+
11+
*Given a collection of candidate numbers (candidates) and a target number (target), the task is to find all unique combinations in candidates where the numbers sum to the target. Each number may be used at most once in a combination.*
12+
13+
*Constraints typically include:<br>
14+
- Each input number is a positive integer.<br>
15+
- The same combination should not be included more than once in the result.*
16+
17+
---
18+
19+
## 💡 Approach & Key Insights
20+
21+
*The main idea is to perform backtracking (recursion with pruning):<br>
22+
- Sort the array to handle duplicates easily.<br>
23+
- At each recursive call, iterate through candidates starting from the current index.<br>
24+
- Skip duplicates by checking if the current element is the same as the previous.<br>
25+
- Use a temporary list to store current combination and subtract from the target as we recurse.<br>
26+
- If target == 0, add the temporary list to the result.<br>
27+
- Backtrack by removing the last added number to try other possibilities.*
28+
29+
---
30+
31+
## 🛠️ Breakdown of Approaches
32+
33+
### 1️⃣ Brute Force / Naive Approach
34+
35+
- **Explanation:** *Try every possible combination using backtracking. Use extra space to store combinations and avoid duplicates by checking previously seen values. Sorting helps ensure duplicates are adjacent, allowing us to skip them efficiently.*
36+
- **Time Complexity:** *O(2^n) – in the worst case, every subset is explored.*
37+
- **Space Complexity:** *O(n * k) – where k is the number of combinations.*
38+
- **Example/Dry Run:**
39+
40+
```plaintext
41+
Input: candidates = [10,1,2,7,6,1,5], target = 8
42+
Sorted: [1,1,2,5,6,7,10]
43+
44+
Possible unique combinations:
45+
[1,1,6], [1,2,5], [1,7], [2,6]
46+
```
47+
48+
---
49+
50+
## 📊 Complexity Analysis
51+
52+
| Approach | Time Complexity | Space Complexity |
53+
| ------------- | --------------- | ---------------- |
54+
| Brute Force | O(2^n) | O(n × k) |
55+
56+
---
57+
58+
## 📉 Optimization Ideas
59+
60+
*Although this problem is inherently exponential due to subset generation, pruning steps (like breaking early when arr[i] > target and skipping duplicates) significantly reduce runtime in practice.*
61+
62+
---
63+
64+
## 📌 Example Walkthroughs & Dry Runs
65+
66+
```plaintext
67+
Example 1:
68+
Input: candidates = [10,1,2,7,6,1,5], target = 8
69+
Sorted: [1,1,2,5,6,7,10]
70+
71+
Recursive Tree (Simplified):
72+
Start at index 0 with target = 8
73+
- Choose 1 → target = 7
74+
- Choose 1 → target = 6
75+
- Choose 6 → target = 0 → valid → [1,1,6]
76+
- Backtrack
77+
- Choose 2 → target = 5
78+
- Choose 5 → target = 0 → valid → [1,2,5]
79+
- Choose 7 → target = 0 → valid → [1,7]
80+
- ...
81+
- Choose 2 → target = 6
82+
- Choose 6 → target = 0 → valid → [2,6]
83+
84+
Output: [[1,1,6], [1,2,5], [1,7], [2,6]]
85+
86+
Example 2:
87+
Input: candidates = [2,5,2,1,2], target = 5
88+
Sorted: [1,2,2,2,5]
89+
90+
Output: [[1,2,2],[5]]
91+
```
92+
93+
---
94+
95+
## 🔗 Additional Resources
96+
97+
- [Python Backtracking Basics](https://www.geeksforgeeks.org/dsa/backtracking-algorithm-in-python/)
98+
- [Sorting for Duplicate Handling](https://docs.python.org/3/howto/sorting.html)
99+
100+
---
101+
102+
Author: Neha Amin <br>
103+
Date: 19/07/2025
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
class Solution {
2+
public:
3+
void findCombination(int ind, int target, vector<int>& arr, vector<vector<int>>& ans, vector<int>& ds) {
4+
if (target == 0) {
5+
ans.push_back(ds);
6+
return;
7+
}
8+
for (int i = ind; i < arr.size(); i++) {
9+
if (i > ind && arr[i] == arr[i - 1]) continue;
10+
if (arr[i] > target) break;
11+
ds.push_back(arr[i]);
12+
findCombination(i + 1, target - arr[i], arr, ans, ds);
13+
ds.pop_back();
14+
}
15+
}
16+
17+
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
18+
sort(candidates.begin(), candidates.end());
19+
vector<vector<int>> ans;
20+
vector<int> ds;
21+
findCombination(0, target, candidates, ans, ds);
22+
return ans;
23+
}
24+
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
class Solution:
2+
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
3+
ans = []
4+
ds = []
5+
candidates.sort()
6+
7+
def findCombination(ind: int, target: int):
8+
if target == 0:
9+
ans.append(ds[:])
10+
return
11+
for i in range(ind, len(candidates)):
12+
if i > ind and candidates[i] == candidates[i - 1]:
13+
continue
14+
if candidates[i] > target:
15+
break
16+
ds.append(candidates[i])
17+
findCombination(i + 1, target - candidates[i])
18+
ds.pop()
19+
20+
findCombination(0, target)
21+
return ans

0 commit comments

Comments
 (0)