leetcode 77. 组合
问题描述
给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。
示例:
输入: n = 4, k = 2
输出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
问题分析
代码
//未剪枝代码
class Solution {
public:
vector<vector<int>> combine(int n, int k) {
vector<vector<int>> ans;
vector<int> path;
backtrack(1,k,n,path,ans);
return ans;
}
void backtrack(int fir,int k,int n,vector<int> &path,vector<vector<int>> &ans)
{
if(path.size() == k)
{
ans.push_back(path);//满足路径长度,则返回
return;
}
for(int i = fir; i <= n ; ++i)
{
path.push_back(i);
backtrack(i+1,k,n,path,ans);
path.pop_back();
}
}
};
结果
执行用时 :184 ms, 在所有 cpp 提交中击败了32.03%的用户
内存消耗 :11.7 MB, 在所有 cpp 提交中击败了83.64%的用户
我们来看看为什么for循环中的i <= n可以替换为i <= n - (k - path.size()) + 1,我们通过几个例子来说明,如果取n = 6,k = 4:
- path.size() == 1,则path中能加3个元素,这时i最大可取4,因为i > 4后就凑不齐3个元素无解了;
- path.size() == 2,则path中能加2个元素,这时i最大可取5,因为i > 5后就凑不齐2个元素无解了;
- path.size() == 3,则path中能加1个元素,这时i最大可取6,因为i > 6后就凑不齐1个元素无解了;
通过上面观察可以知道i不必遍历到n,能添加的元素个数为k - path.size(),设能添加的最大元素是m,则m满足m + k - path.size() = n + 1(3+4=2+5=1+6=7),因此m = n + 1 - (k - path.size()).
//剪枝代码
class Solution {
public:
vector<vector<int>> combine(int n, int k) {
vector<vector<int>> ans;
vector<int> path;
backtrack(1,k,n,path,ans);
return ans;
}
void backtrack(int fir,int k,int n,vector<int> &path,vector<vector<int>> &ans)
{
if(path.size() == k)
{
ans.push_back(path);//满足路径长度,则返回
return;
}
for(int i = fir; i <= n - (k - path.size()) + 1; ++i)
{
path.push_back(i);
backtrack(i+1,k,n,path,ans);
path.pop_back();
}
}
};
结果
执行用时 :76 ms, 在所有 cpp 提交中击败了97.21%的用户
内存消耗 :11.8 MB, 在所有 cpp 提交中击败了76.95%的用户