题目:
Given two integers n and k, return all possible combinations of k numbers out of 1 … n.
Example:
Input: n = 4, k = 2
Output:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
解法1:
回溯法
和常规的回溯法一样,在循环条件可以做一点优化,未优化前
for(int i = start; i <= n; ++i){
优化后
for(int i = start; i <= n - (k -path.size()) + 1; ++i){
以n = 4, k = 2为例
1、在path未加入任何元素时,对应下图中的第一层,这时候我们 i 最多循环到n - (k -path.size()) + 1 = 4 - (2 - 0)+ 1 = 3
因为3,4正好满足path的要求,为两个元素,而循环到4,只剩下一个元素无论如何都不可能再有两个元素出现
2、在path未加入1个元素时,对应下图中的第二层,这时候我们 i 最多循环到n - (k -path.size()) + 1 = 4 - (2 - 1)+ 1 = 4
因为这次我们只需要再加1个元素就好,所以4也是可以的
c++:
class Solution {
public:
vector<vector<int>> combine(int n, int k) {
vector<vector<int>> res;
vector<int> path;
DFS(n, k, path, res, 1);
return res;
}
void DFS(int n, int k, vector<int>& path,vector<vector<int>>& res,int start){
if(path.size() == k){
res.push_back(path);
return;
}
for(int i = start; i <= n - (k -path.size()) + 1; ++i){
path.push_back(i);
DFS(n,k, path, res, i+1);
path.pop_back();
}
}
};
java:
class Solution {
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
DFS(n,k, path, res, 1);
return res;
}
private void DFS(int n,int k, List<Integer> path,List<List<Integer>> res,int start){
if(path.size() == k){
res.add(new ArrayList<>(path));
return;
}
for(int i = start; i <= n - (k -path.size()) + 1 ; ++i){
path.add(i);
DFS(n,k, path, res, i+1);
path.remove(path.size() - 1);
}
}
}
python:
class Solution(object):
def combine(self, n, k):
"""
:type n: int
:type k: int
:rtype: List[List[int]]
"""
res = []
self.DFS(n,k, [], res, 1)
return res
def DFS(self, n,k, path, res,start):
if len(path) == k:
res.append(path)
return
for i in xrange(start, n - (k - len(path)) + 2):
self.DFS(n,k, path + [i], res, i+1)