【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;
}
};

 

posted @ 2015-01-20 22:59  匡子语  阅读(226)  评论(0编辑  收藏  举报