Medium!
题目描述:
给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。
示例:
输入: n = 4, k = 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]
解题思路:
这道题让求1到n共n个数字里k个数的组合数的所有情况,还是要用深度优先搜索DFS来解,根据以往的经验,像这种要求出所有结果的集合,一般都是用DFS调用递归来解。那么我们建立一个保存最终结果的大集合res,还要定义一个保存每一个组合的小集合out,每次放一个数到out里,如果out里数个数到了k个,则把out保存到最终结果中,否则在下一层中继续调用递归。https://blog.csdn.net/u010500263/article/details/18435495中有一张图很好的说明了递归调用的顺序。
C++解法一:
1 class Solution { 2 public: 3 vector<vector<int>> combine(int n, int k) { 4 vector<vector<int>> res; 5 vector<int> out; 6 helper(n, k, 1, out, res); 7 return res; 8 } 9 void helper(int n, int k, int level, vector<int>& out, vector<vector<int>>& res) { 10 if (out.size() == k) res.push_back(out); 11 for (int i = level; i <= n; ++i) { 12 out.push_back(i); 13 helper(n, k, i + 1, out, res); 14 out.pop_back(); 15 } 16 } 17 };
对于n = 5, k = 3, 处理的结果如下:
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
我们再来看一种迭代的写法,也是一种比较巧妙的方法。这里每次先递增最右边的数字,存入结果res中,当右边的数字超过了n,则增加其左边的数字,然后将当前数组赋值为左边的数字,再逐个递增,直到最左边的数字也超过了n,停止循环。对于n=4, k=2时,遍历的顺序如下所示:
0 0 #initialization
1 0
1 1 #push_back
1 2 #push_back
1 3 #push_back
1 4 #push_back
1 5
2 5
2 2 #push_back
2 3 #push_back
2 4 #push_back
...
3 4 #push_back
3 5
4 5
4 4
4 5
5 5 #stop
C++解法二:
1 class Solution { 2 public: 3 vector<vector<int>> combine(int n, int k) { 4 vector<vector<int>> res; 5 vector<int> out(k, 0); 6 int i = 0; 7 while (i >= 0) { 8 ++out[i]; 9 if (out[i] > n) --i; 10 else if (i == k - 1) res.push_back(out); 11 else { 12 ++i; 13 out[i] = out[i - 1]; 14 } 15 } 16 return res; 17 } 18 };
原文地址:https://www.cnblogs.com/ariel-dreamland/p/9154419.html
时间: 2024-10-15 10:56:40