题目:
Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.
For example,
If n = 4 and k = 2, a solution is:
[ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]
思路:
1、回溯法:标准解法是采用深度优先搜索的回溯。对于每一个在[1, n]之间的数x,我们从两条路径启动下一轮搜索,一条是将x包含在结果中,另一条是不将x包含在结果中。必须注意控制两类边界条件:1)k == 0,代表目前已经找到了一个符合条件的答案;2)cur > n,表示搜索已经超出了n的范围。
2、分治法:还有一种很巧妙的思路就是分治法。对于从[1, n]中选择k个数来说,其结果可以分为两类,一类包含n,另一类不包含n。如果我们分别递归地求得了这两类答案,则直接将这两类答案合并就可以返回最终结果。这里需要注意两个递归的边界条件:1)k == 1,表示只需要从[1, n]中选择一个数而已;2)k == n(表示所有的数都要加入到 结果中)。
代码:
1、回溯法:
class Solution {
public:
vector<vector<int>> combine(int n, int k) {
vector<vector<int>> ret;
if (n < 1 || n < k) {
return ret;
}
vector<int> line;
dfs(ret, line, 1, n, k);
return ret;
}
private:
void dfs(vector<vector<int>> &ret, vector<int> &line, int cur, int n, int k) {
if (k == 0) {
ret.push_back(line);
return;
}
if(cur > n) {
return;
}
line.push_back(cur); // add cur to the result
dfs(ret, line, cur + 1, n, k - 1);
line.pop_back();
dfs(ret, line, cur + 1, n, k); // do not add cur to the result
}
};
2、分治法:
class Solution {
public:
vector<vector<int>> combine(int n, int k) {
return combine(1, n, k);
}
private:
vector<vector<int>> combine(int low, int high, int k)
{
vector<vector<int>> combination;
if(k == 1) { // base 1: only one number need to be added
for(int i = low; i <= high; i++) {
vector<int> temp;
temp.push_back(i);
combination.push_back(temp);
}
}
else if(k == high - low + 1) { // base 2: all numbers need to be added
vector<int> temp;
for(int i = low; i <= high; ++i)
temp.push_back(i);
combination.push_back(temp);
}
else { // need to solve this problem recursively
// the results that contain the last number
vector<vector<int>> combination1 = combine(low, high - 1, k - 1);
for(int i = 0; i < combination1.size(); ++i) {
combination1[i].push_back(high);
combination.push_back(combination1[i]);
}
// the results that do not contain the last number
vector<vector<int>> combination2 = combine(low, high - 1, k);
for(int i = 0; i < combination2.size(); ++i) {
combination.push_back(combination2[i]);
}
}
return combination;
}
};