• 【Combinations】cpp


    题目:

    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],
    ]

    代码:

    class Solution {
    public:
        vector<vector<int>> combine(int n, int k) {
                vector<vector<int> > ret;
                if ( n<k ) return ret;
                vector<int> tmp;
                Solution::dfs(ret, 1, k, n, 0,tmp);
                return ret;    
        }
        static void dfs(vector<vector<int> >& ret, int index, int k, int n, int step, vector<int>& tmp)
        {
                if ( step==k )
                {
                    ret.push_back(tmp);
                    return;
                }
                for ( size_t i = index; i <=n; ++i )
                {
                    tmp.push_back(i);
                    Solution::dfs(ret, i+1, k, n, step+1, tmp);
                    tmp.pop_back();
                }
        }
    };

    tips:

    dfs解法。

    几个参数的含义:

    ret: 存储返回combination结果

    index: 当前起始元素是多大

    k,n:与题意所给相同

    step:深入到第几层

    思路:dfs的每层增加一个元素,直到深度等于k返回结果;如果从index开始的元素不足以打到深度k,则不会添加到ret中。

    ======================================

    其实,可以不用传入6个参数,传入5个足以。代码如下:

    class Solution {
    public:
        vector<vector<int>> combine(int n, int k) {
                vector<vector<int> > ret;
                if ( n<k ) return ret;
                vector<int> tmp;
                Solution::dfs(ret, 1, k, n, tmp);
                return ret;    
        }
        static void dfs(vector<vector<int> >& ret, int index, int k, int n, vector<int>& tmp)
        {
                if ( tmp.size()==k )
                {
                    ret.push_back(tmp);
                    return;
                }
                for ( size_t i = index; i <=n; ++i )
                {
                    tmp.push_back(i);
                    Solution::dfs(ret, i+1, k, n, tmp);
                    tmp.pop_back();
                }
        }
    };

    用tmp.size()代替step,代码跟简洁一些,因此更推崇后一种方法。

    =======================================

    leetcode写到这里有些感觉了,搜了一下dfs bfs的模板相关的内容,基本跟实战中的经验差不多:

    http://blog.csdn.net/fightforyourdream/article/details/12866861

    http://www.cnblogs.com/HectorInsanE/archive/2010/11/09/1872656.html

    =======================================

    再补上一种迭代的解法,如下:

    class Solution {
    public:
        vector<vector<int>> combine(int n, int k) {
                vector<vector<int> > ret;
                // corner cases
                if ( n<k || k==0 ) return ret;
                // initialization
                for ( int i = 0; i < n-k+1; ++i ) 
                {
                    vector<int> tmp;
                    tmp.push_back(i+1);
                    ret.push_back(tmp);
                }
                // combines
                for ( int i = 0; i < k-1; ++i )
                {
                    vector<vector<int> > tmp = ret;
                    ret.clear();
                    for ( int j = 0; j < tmp.size(); ++j )
                    {
                        int curr = tmp[j].back();
                        for ( int v = curr+1; v <= n; ++v )
                        {
                            vector<int> ori = tmp[j];
                            ori.push_back(v);
                            ret.push_back(ori);
                        }
                    }
                }
                return ret;    
        }
    };

    tips:

    1. 这种迭代方式返回的组合内部都是由小到大排序的。

    2. intialization的含义是”组合首个元素最小到最大“(比如n=4,k=2 按照原则1,则首个元素最大取到3,因为比4小的元素没有了不足以满足k=2的条件)

    3. 每轮迭代,先取出来当前组合最后一个元素(最大的)curr;再从curr+1到n挨个取值,补到tmp[j]的后面,构成新的组合。

    4. 控制迭代的次数是k-1次(因为initialization已经算了一次)

    ===============================================

     第二次过这道题,用dfs过的,传入参数比第一次过更简洁一些。

    class Solution {
    public:
            vector<vector<int> > combine(int n, int k)
            {
                vector<vector<int> > ret;
                vector<int> tmp;
                Solution::dfs(ret, tmp, n, k);
                return ret;
            }
            static void dfs(
                vector<vector<int> >& ret, 
                vector<int>& tmp, 
                int n, int k)
            {
                if ( tmp.size()==k )
                {
                    ret.push_back(tmp);
                    return;
                }
                int index = tmp.empty() ? 0 : tmp.back();
                for ( int i=index+1; i<=n; ++i )
                {
                    tmp.push_back(i);
                    Solution::dfs(ret, tmp, n, k);
                    tmp.pop_back();
                }
            }
    };
  • 相关阅读:
    【HAOI2014】贴海报
    【HAOI2016】食物链
    【NOI2003】银河英雄传
    【HAOI2013】花卉节
    【BZOJ1702】[usaco2007margold]队列平衡
    【网络流24】餐巾
    洛谷 [P1265] 公路修建
    全排列与 康托展开
    洛谷 [P1403] 约数研究
    高精度模板
  • 原文地址:https://www.cnblogs.com/xbf9xbf/p/4520749.html
Copyright © 2020-2023  润新知