組合數列印

來源:互聯網
上載者:User
組合數列印

//[北京直真筆試題]比如給定4個數,分別為1,2,3,4。現在要求從中選取3個的組合數,不能重複。

即列印:123,124,234...。

方法1:【思路】1)將1,2,3,4存入數組中,然後從4個數中選出1個數,即為selVal;2)接下來的工作即是從剩餘的3個數中選取2個數,需要儲存除selVal外的剩餘3個數;3)選取後列印selVal和選的2個數即可。

【分析】:時間複雜度O(n3),空間複雜度O(n)。

const int g_nCnt = 4;int g_nArr[g_nCnt] ={1,2,3,4};//從3個裡面選2個數的相片順序.void selTwoFromThree(intnArray[], int nSize, int nAlreadySel){for(int i = 0; i < nSize; i++)   {           for(int j = i+1; j < nSize; j++)           {                    cout << nAlreadySel << "\t"<< nArray[i] << "\t" << nArray[j] << endl; //先i後j                    cout << nAlreadySel << "\t"<< nArray[j] << "\t" << nArray[i] << endl; //先j後i           }  }} void printArray(intnArray[], int nSize){int nAleardySel = 0;for(int i = 0; i < nSize; i++){           int *pArrAdd = new int[3];           int k = 0;           nAleardySel = nArray[i];           for(int j = 0; j < nSize; j++)           {                    if(nArray[j] != nAleardySel)                    {                             pArrAdd[k++] = nArray[j];                    }//end if           }//end for j                     selTwoFromThree(pArrAdd,g_nCnt-1,nAleardySel);           cout << endl;}//end fori}

方法2:【思路】 將4個數中選擇的3個數看做百位元,因此就變成了列印的過程,變成了從4個數中選3個數組成的全排列4*4*4=64個中選擇百位、十位、個位不重複的4*3*2=24個數的過程。

【分析】:時間複雜度O(n3),空間複雜度O(1)。不需要額外的開闢空間。

#define MAXN 4void combineSelPrint(intmaxCnt){static int count = 0;for(int i=1;i<=MAXN;i++)//百位的情況{           for(int j=1;j<=MAXN;j++)//十位的情況           {                    if(j != i)                    {                             for(int k=1;k<=MAXN;k++)//個位的情況                             {                                       if(k != j && k != i)                                       {                                                printf("%d,%d,%d\n",i,j,k);                                                ++count;                                       }                             }//end for k                    }//end if j           }//end for j}//end for icout << "--------------count = " << count<< "-------------" << endl;}  int main(){combineSelPrint(MAXN);return 0;}

【思考?】:有沒有時間複雜度低的演算法?或者遞迴實現的好方法?

【方法3】:遞迴實現組合數列印,C(n,m),從n個數中選出m個數(m<=n)個的全部組合列印。

有很多文章討論如何列印全排列的,畢竟它是很多遍曆問題的基礎嘛。這裡介紹的是如何列印組合數。
先看一個例子:
C(5,3) = 10
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5

大家注意到沒有,
1 | 2 3
1 | 2 4
1 | 2 5
1 | 3 4
1 | 3 5
1 | 4 5
------ C(4, 2)∵可以在{2, 3, 4, 5}中挑2個出來。
2 | 3 4
2 | 3 5
2 | 4 5
------ C(3, 2)∵可以在{3, 4, 5}中挑2個出來。
3 | 4 5
------ C(2, 2)∵只能在{4, 5}中挑2個出來。

 

這樣就很容易寫出遞迴演算法來。
Algorithm combination(n, k, A[l..n+l-1])
1. if k = 0
2. print ary[1..k]
3. else
4. for i←1 to n-k+1
5. ary[index++] = A[l+i-1]
6. combination(n-i,k-1, A[l+i..n+l-1])
7. --index
8. endfor
大家可能會疑惑幹嘛要弄出個index,還有一加一減的(你手工算一下就知道了)。

 

【實現部分】

int *dst_array,top=0;//中間數組,存放中間求解過程,count計數所有的組合個數int cnt = 0; //列印長度為n的數組元素static void printA(int*parray,int n){    int i;    for(i=0;i<n;i++)    {        printf("%d ",parray[i]);    }} //遞迴列印組合數static  void print_combine(int *pArray,int n,int m){    if(n < m || m==0)      {           return ;//情況一:不符合條件,返回    }     print_combine(pArray+1,n-1,m);//情況二:不包含當前元素的所有的組合     dst_array[top++]=pArray[0];//情況三:包含當前元素    if(m==1)     {  //情況三-1:截止到當前元素        printA(dst_array,top);        printf("\n");        cnt++;        top--;        return;    }     print_combine(pArray+1,n-1,m-1);//情況三-2:包含當前元素但尚未截止    top--;//返回前恢複top值} int main(){    int n,m,*parray;//存放資料的數組,及n和m    printf("---以下實現從n個數中選出m個數的全組合列印(n個數為1,2,3....n---\n");    printf("---請輸入n 和m \n---");    scanf("%d%d",&n,&m);     printf("\n---以下是輸出結果---\n");    parray=(int *)malloc(sizeof(int)*n);    dst_array=(int *)malloc(sizeof(int)*m);     int i;    for(i=0;i<n;i++)    {           //初始化數組        //scanf("%d",&parray[i]);           parray[i] = i+1;    }    print_combine(parray,n,m);//求數組中所有數的組合     printf("=====C(%d,%d)共計:%d個=====",n,m,cnt);     free(parray);    free(dst_array);    return 0;}

       方法三參考:http://bbs.pfan.cn/post-270256.html

     http://blog.csdn.net/challenge_c_plusplus/article/details/6641950

    筆者調試了方法三,好用。但是筆者對其中遞迴的部分的原理甚是不解,有些疑惑,望大家介紹下。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.