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], ]
思路:有点像0-1背包问题, 对于从1-n的每一个数字都可以选择放入答案 和不放入答案。 当长度达到k时就是一个符合条件的解。
递归的代码,AC了。只要注意状态的还原就好。
#include <iostream> #include <vector> #include <algorithm> #include <queue> #include <stack> using namespace std;class Solution { public:vector<vector<int> > combine(int n, int k) {vector<vector<int>> ans;combinepart(ans, 1, k, n);return ans;}void combinepart(vector<vector<int>> &ans, int num, int k, int n){static int i = 0;static vector<int> partans;if(num - 1 > n || partans.size() + (n - num + 2) < k) return; //数字超过了n 或者即使后面数字全部压入长度也不够的时候 直接返回 避免不必要的计算if(i == k){ans.push_back(partans);return;}partans.push_back(num); //放入numi++;combinepart(ans, num + 1, k, n);partans.pop_back();i--;combinepart(ans, num + 1, k, n);//不放入num } };int main() {Solution s;vector<vector<int>> ans = s.combine(3,3);return 0; }
网上有非递归的代码,可是我好困,懒得看... 速度都差不多的,因为我的递归截枝了,没有多余的操作。
class Solution { public:vector<vector<int> > combine(int n, int k) {vector<vector<int> >ret;if(k>n||k<=0)return ret;for(int i=1;i<=n-k+1;i++){ret.push_back(vector<int>(1,i));}for(int i=2;i<=k;i++){int num=ret.size();for(int j=0;j<num;j++){int last=ret[j].back();vector<int> pretmp=ret[j];ret[j].push_back(last+1);for(int p=last+2;p+k-i<=n;p++){vector<int> tmp=pretmp;tmp.push_back(p);ret.push_back(tmp);}}}return ret; } };