1. 程式人生 > >java排列組合遞迴實現

java排列組合遞迴實現

import java.util.Scanner;

public class combination {
            public static int k1=0;     //計數k1
            public static int k2=0;     //計數k2

            /*全排列統計個數*/
            public static int count(int n){
                        if(n==0){
                                    return 1;
                        }
                        return n*count(n-1);
            }


            /*排列統計個數*/
            public static int p_count(int m,int n){
                        return count(m)/count(n);
            }


            /*組合統計個數*/
            public static int c_count(int m,int n){
                        return count(m)/(count(n)*count(m-n));
            }

            /*交換*/
   public static void swap(int[] list,int a,int b){
               int temp;
               temp=list[a];
               list[a]=list[b];
               list[b]=temp;

   }

   /*排列*/
   public static void permu(int[] list,int m,int n,int u){
               if(m==list.length-u+1){
                           k1++;
                           System.out.print("第"+k1+"種排列:   ");
                           for(int i=0;i<list.length-u+1;i++)
                                       System.out.print(list[i]);
                           System.out.println();
               }else{
                                       for(int i=m;i<=n;i++){  // 從後往前依次選定一個
                                       swap(list,m,i);                // 選定一個後
                                       permu(list,m+1,n,u);    //  對m+1後面繼續進行遞迴
                                       swap(list,m,i);              //在最後兩個數字之間交換位置,實現兩個數字的全排列
                                      }
               }
   }


            /*組合*/

   public static void comb(int[] list, int n, int m, int[] sub,int k) {
       if (m == 0) {

               k2++;
               System.out.print("第"+k2+"種組合:   ");
           for (int i = 0; i <k; ++i) {
               System.out.print(sub[i]);
           }
           System.out.println();
       } else {
           for (int i = n; i >= m; --i) {    // 從後往前依次選定一個
               sub[m - 1] = list[i - 1];      // 選定一個後
               comb(list, i - 1, m - 1, sub,k); // 從前i-1個裡面選取m-1個進行遞迴
           }
       }
   }

/*主函式*/
            public static void main(String[] args) {
                        Scanner scan=new Scanner(System.in);
                        int[] array={0,1,2,3,4,5,6,7,8,9};
                        int[] sub = new int[array.length];          //儲存子組合資料的陣列
                        System.out.println("----------------------選擇操作-------------------");
                        System.out.println("---------0 :10選4的組合   1:全排列---------");
                        System.out.print("請輸入操作:");
                        int c=scan.nextInt();
                        if(c==1){
                                    System.out.println("10個數字的全排列個數為:"+p_count(10,1));            //A(10,1)
                                    permu(array,0,9,1);                         //A(10,1)種情況的列出
                        }
                        if(c==0){
                                    System.out.println("10選4的組合個數為:"+c_count(10,4));                 //C(10,4)
                                    comb(array, array.length, 4, sub,4);    //C(10,4)種情況的列出
                        }
                        if(c!=0&&c!=1)
                                    System.out.println("輸入有誤!");
            }
}

/**
 *  n個元素選m個元素的組合問題的實現. 原理如下:
 *  從後往前選取, 選定位置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的遞迴.
 */