【leetcode】Combinations (middle)
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); //放入num i++; 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; } };