• 打印从n个数种选取m个数的组合数


    摘自 http://blog.csdn.net/wumuzi520/article/details/8087501#comments

    方法一:利用递归思想。

    代码如下:

    //从后往前选取,选定位置i后,再在前i-1个里面选取m-1个。

    //如 1 2 3 4 5 中选取 3 个

    //1、选取5后,再在前4个里面选取2个,而前4个里面选取2个又是一个子问题,递归即可。

    //2、如果不包含5,直接选定4,那么再在前3个里面选取2个,而前三个里面选取2个又是一个子问题,递归即可。

    //3、如果也不包含4,直接选取3,那么再在前2个里面选取2个,刚好只有两个。

    //纵向看,1、2、3刚好是一个for循环,初值为5,终值为m

    //横向看,该问题为一个前i-1个中选m-1的递归。

    void Combination(int arr[], int nLen, int m, int out[], int outLen) 

        if(m == 0) 

        { 

            for (int j = 0; j < outLen; j++) 

                cout << out[j] << " "; 

            cout << endl; 

            return; 

        } 

     

        for (int i = nLen; i >= m; --i)  //从后往前依次选定一个

        { 

            out[m-1] = arr[i-1]; //选定一个后

            //从前i-1个里面选取m-1个进行递归

            Combination(arr, i - 1, m - 1, out, outLen);

        } 

     

    void PrintCombination(int arr[], int nLen, int m) 

        if(m > nLen) 

        return; 

     

        int* out = new int[m]; 

        Combination(arr, nLen, m, out, m); 

        delete [] out; 

    }

    方法二:二进制组合算法:
      思路是开一个数组,其下标表示1到m个数,数组元素的值为1表示其下标
      代表的数被选中,为0则没选中。  
      首先初始化,将数组前n个元素置1,表示第一个组合为前n个数。  
      然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为“01”组合,同时将其左边的所有“1”全部移动到数组的最左端(只有第一位变为0才需要移动,否则其左边的1本来就在最左端,无需移动)。  
      当第一个“1”移动到数组的m-n的位置,即n个“1”全部移动到最右端时,就得到了最后一个组合。  
      例如求5中选3的组合:  
      1   1   1   0   0   //1,2,3  
      1   1   0   1   0   //1,2,4  
      1   0   1   1   0   //1,3,4  
      0   1   1   1   0   //2,3,4  
      1   1   0   0   1   //1,2,5  
      1   0   1   0   1   //1,3,5  
      0   1   1   0   1   //2,3,5  
      1   0   0   1   1   //1,4,5  
      0   1   0   1   1   //2,4,5  
      0   0   1   1   1   //3,4,5

    代码如下:

    void Combine(int arr[], int n, int m)
    {
        if(m > n)
            return;

        int* pTable = new int[n];        //定义标记buf并将其前m个置1
        memset(pTable, 0, sizeof(int) * n);
        for(int i = 0; i < m; ++i)
            pTable[i] = 1;

        bool bFind = false;
        do
        {
            for (int i = 0; i < n; i++)    //打印当前组合
            {
                if(pTable[i])
                    cout << arr[i] << " ";
            }
            cout << endl;

            bFind = false;
            for(int i = 0; i < n-1; i++)
            {
                if(pTable[i]==1 && pTable[i+1]==0)
                {
                    swap(pTable[i], pTable[i+1]);    //调换10为01
                    bFind = true;

                    //如果第一位为0,则将第i位置之前的1移到最左边,如为1则第i位置之前的1就在最左边,无需移动

                    if(pTable[0] == 0)   
                    {
                        //O(n)复杂度使1在前0在后

                        for (int k=0, j=0; k < i; k++)   
                        {
                            if(pTable[k])
                            {
                                swap(pTable[k],pTable[j]);
                                j++;
                            }
                        }
                    }

                    break;
                }
            }
        } while (bFind);

        delete [] pTable;
    }

  • 相关阅读:
    使用math.js进行javascript精确计算
    SpringMVC java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name
    MAC系统下配置环境变量
    javaURL中文乱码的问题
    Mac系统搭建java开发环境
    mysql 删除重复数据保留只保留一条
    SSM 加载配置文件
    CSS3实现元素旋转
    CSS3实现圆角效果
    CSS3 -web-box-shadow实现阴影效果
  • 原文地址:https://www.cnblogs.com/GlassHour/p/5784273.html
Copyright © 2020-2023  润新知