java排列組合遞迴實現
阿新 • • 發佈:2018-12-11
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的遞迴. */