吃完中饭,笔者又刷了一道题,下面就和大家分享一下经验吧!
题目如下:
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],
]
题意分析:
给定两个整数n、k,请返回由1到n之间的k个数构成的所有组合数。
方法一(递归回溯法)
与排列不同的是组合不需要考虑元素的位置关系,因此可直接对固定位置的各元素求解即用start持续前进,故可以参照“https://blog.csdn.net/Vensmallzeng/article/details/96473991”中的方法一进行求解,不过这里的递归终止条件有些变化,应该是temp.size()等于k时则保存temp结果到res中。
解题代码如下:
class Solution{
public:
vector<vector<int>> combine(int n, int k){
vector<vector<int>> res;
vector<int> temp;
if (n==0) return res;
Findcombine(n, k, 1,temp, res);
return res;
}
void Findcombine(int n, int k, int start, vector<int>& temp, vector<vector<int>>& res){
if (temp.size()==k) {
res.push_back(temp);
return;
}
for (int i = start; i <= n; i++) {
temp.push_back(i);
Findcombine(n, k, i+1,temp, res);
temp.pop_back();
}
}
};
提交后的结果如下:
方法二(方法一优化)
对方法一中的递归处进行剪枝操作,因为每当循环到k-temp.size()时,已经是最后一种组合情况了,再往后循环都是数目不合法的组合,所以可以对for循环中的条件进行稍加修改以实现递归剪枝。
解题代码如下:
class Solution{
public:
vector<vector<int>> combine(int n, int k){
vector<vector<int>> res;
vector<int> temp;
if (n==0) return res;
Findcombine(n, k, 1,temp, res);
return res;
}
void Findcombine(int n, int k, int start, vector<int>& temp, vector<vector<int>>& res){
if (temp.size()==k) {
res.push_back(temp);
return;
}
for (int i = start; i <= n-(k-temp.size())+1; i++) {
temp.push_back(i);
Findcombine(n, k, i+1,temp, res);
temp.pop_back();
}
}
};
提交后的结果如下:
日积月累,与君共进,增增小结,未完待续。