77. Combinations Medium
Given two integers n and k, return all possible combinations of k numbers chosen from the range [1, n].
You may return the answer in any order.
Example 1:
Input: n = 4, k = 2
Output:
[ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4] ]
Example 2:
Input: n = 1, k = 1
Output: [[1]]
Approach
Input: Two integers n and k
Output: Return all possible combinations of k numbers chosen from the range [1, n]
This problem belongs to Combination Backtracking problems.
Three Questions of Backtracking
- Current Operation?
- At the current position
i, try to choose a numberjand place it intopath. - That is: place the number
j(j ∈ [i, 1]) into the pathpath, indicating "I have selected it".
- At the current position
- Sub-problem?
- After choosing the number
j, we need to continue selecting the remaining numbers, and the maximum value of the remaining numbers cannot exceedj-1(because we cannot select repeatedly). - That is: recursively call
dfs(j-1)to continue constructing the remaining combination.
- After choosing the number
- Next Sub-problem?
- The next recursive step starts from
dfs(j-1), continuing to pick numbers. - This is the "branching down", meaning continuing to choose from the remaining numbers.
- The next recursive step starts from
Pruning Conditions
- When the number of remaining available digits is smaller than
k - len(path), there is no need to try anymore, because it is impossible to gather k numbers.
Implementation
python
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
ans = [] # Final result, stores all combinations
path = [] # Current combination path
def dfs(i):
# The number of available digits remaining must be ≥ the number of digits still needed
# Pruning: if the remaining digits are not enough to fill the path, return directly
if i < k - len(path):
return
# If k numbers have been selected, add the current scheme to the result
if len(path) == k:
ans.append(path.copy())
return
# Pick numbers from largest to smallest to avoid duplicate combinations (each number is picked once)
for j in range(i, 0, -1):
path.append(j) # Select current number
dfs(j - 1) # Continue selecting the rest of the numbers
path.pop() # Backtrack, undo the choice
dfs(n) # Start recursion from n
return ansjavascript
/**
* @param {number} n
* @param {number} k
* @return {number[][]}
*/
const combine = function(n, k) {
ans = []
path = []
function dfs(i) {
const d = k - path.length;
if (i < d) return;
if (path.length == k) {
ans.push([...path]);
return;
}
for (let j = i; j > 0; j--) {
path.push(j);
dfs(j - 1);
path.pop();
}
}
dfs(n);
return ans;
};Complexity Analysis
- Time Complexity:
O(n * 2^n) - Space Complexity:
O(n * 2^n)