@@ -74,3 +74,123 @@ Using 4 different numbers in the range [1,9], the smallest sum we can get is 1+2
7474
7575- Array
7676- Backtracking
77+
78+ ## Combination
79+
80+ Given two integers n and k, return all possible combinations of k numbers chosen from the range [ 1, n] .
81+
82+ You may return the answer in any order.
83+
84+ > Note: Combinations are unordered, i.e., [ 1, 2] and [ 2, 1] are considered the same combination.
85+
86+ ### Examples
87+
88+ Example 1:
89+ ``` text
90+ Input: n = 4, k = 2
91+ Output: [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
92+ Explanation: There are 4 choose 2 = 6 total combinations.
93+ Note that combinations are unordered, i.e., [1,2] and [2,1] are considered to be the same combination.
94+ ```
95+
96+ Example 2:
97+ ``` text
98+ Input: n = 1, k = 1
99+ Output: [[1]]
100+ Explanation: There is 1 choose 1 = 1 total combination.
101+ ```
102+
103+ ### Constraints
104+
105+ - 1 <= n <= 20
106+ - 1 <= k <= n
107+
108+ ### Topics
109+
110+ - Backtracking
111+
112+ ### Solutions
113+
114+ #### Variation 1
115+
116+ - Create an empty list ` result ` to store the final combinations and an empty list ` stack ` to store the current combination being
117+ formed.
118+ - Define a recursive function ` backtrack(start) ` , which will generate all possible combinations of size ` k ` from the
119+ numbers starting from ` start ` up to ` n ` .
120+ - In the backtrack function:
121+ - If the length of ` stack ` becomes equal to ` k ` , it means we have formed a valid combination, so we append a copy of
122+ the current comb list to the ` result ` list. We use ` stack[:] ` to create a copy of the list since lists are mutable
123+ in Python, and we want to preserve the combination at this point without being modified later.
124+ - If the length of ` stack ` is not equal to k, we continue the recursion.
125+ - Within the ` backtrack ` function, use a loop to iterate over the numbers starting from ` start ` up to ` n ` .
126+ - For each number ` num ` in the range, add it to the current ` stack ` list to form the combination.
127+ - Make a recursive call to ` backtrack ` with ` start ` incremented by 1. This ensures that each number can only be used
128+ once in each combination, avoiding duplicate combinations.
129+ - After the recursive call, remove the last added number from the ` stack ` list using stack.pop(). This allows us to
130+ backtrack and try other numbers for the current position in the combination.
131+ - Start the recursion by calling ` backtrack(1) ` with start initially set to 1, as we want to start forming combinations
132+ with the numbers from 1 to n.
133+ - After the recursion is complete, the ` result ` list will contain all the valid combinations of size ` k ` formed from the
134+ numbers 1 to n. Return ` result ` as the final result.
135+
136+ The code uses a recursive backtracking approach to generate all the combinations efficiently. It explores all possible
137+ combinations, avoiding duplicates and forming valid combinations of size k. The result res will contain all such
138+ combinations at the end.
139+
140+ ##### Complexity
141+
142+ ###### Time complexity: O(n * k)
143+
144+ ` n ` is the number of elements and ` k ` is the size of the subset. The backtrack function is called n times, because there
145+ are n possible starting points for the subset. For each starting point, the backtrack function iterates through all k
146+ elements. This is because the ` stack ` list must contain all k elements in order for it to be a valid subset.
147+
148+ > The time complexity is T(n,k)=O((n/k) * k), as there are(n/k) possible combinations and each requires O(k) work to build
149+ and copy.
150+
151+ ###### Space complexity: O(k)
152+
153+ The ` stack ` list stores at most k elements. This is because the ` backtrack ` function only adds elements to the ` stack `
154+ list when the subset is not yet complete.
155+
156+ #### Variation 2
157+
158+ The algorithm uses a backtracking strategy to generate all possible combinations of size k from the range [ 1…n] . It
159+ builds each combination step by step, keeping a temporary list path representing the current sequence of chosen numbers.
160+ At every recursive call, the algorithm selects a new number to add to the path and then continues exploring with the next
161+ larger number. If the length of the path becomes equal to k, the combination is complete and is added to the result list.
162+ After exploring one choice, the algorithm backtracks by removing the last number, allowing it to try different alternatives.
163+
164+ To avoid unnecessary work, the recursion stops early whenever the remaining numbers are too few to complete a valid
165+ combination. This pruning ensures the algorithm explores only those paths that can lead to valid results, making it
166+ efficient and systematic in covering all unique combinations without repetition.
167+
168+ The steps of the algorithm are as follows:
169+
170+ 1 . Create an empty list, ` ans ` , to store all valid combinations.
171+ 2 . Define recursive function, ` backtrack(path, start) ` , where:
172+ - ` path ` stores the current partial combination.
173+ - ` start ` is the smallest number that can be chosen next.
174+ 3 . The base case is a complete combination: when ` len(path) == k ` , save it to ans and return.
175+ 4 . Calculate remaining needs:
176+ - Compute ` need = k - len(path) ` (how many more numbers are required).
177+ - Compute ` max_start = n - need + 1 ` (the largest possible starting number that still leaves room to complete the
178+ combination).
179+ 5 . Recursive exploration: For each number ` num ` from ` start ` to ` max_start ` :
180+ - Append ` num ` to ` path ` (choose).
181+ - Call ` backtrack(path, num + 1) ` (explore further).
182+ - Remove ` num ` from ` path ` (backtrack/undo choice).
183+ 6 . Start recursion by calling ` backtrack([], 1) ` with an empty path starting from 1.
184+ 7 . After recursion finishes, return ` ans ` , which contains all valid combinations.
185+
186+ ##### Complexity
187+
188+ ###### Time complexity: O(n * k)
189+
190+ The time complexity is T(n,k)=O((n/k) * k), as there are(n/k) possible combinations and each requires O(k) work to build
191+ and copy.
192+
193+ ###### Space complexity: O(k)
194+
195+ The space complexity is O(k), as the recursion depth can reach k and the path itself holds at most k numbers during
196+ recursion.
0 commit comments