排列和組合問題是演算法中比較常見的問題,在這一節裡,我們將對常見的排列和組合問題進行探討。
(1)給定數字位元和進位,列印出所有的組合。
對於這個問題,按照人的思維,就是對數位每一個位進行不斷選值,如3位2進位數,那麼我們首先取最高位為0,取好後,再對次高位進行選值,次高位選好後,再對最低位取值位0,此時已經對所有位都取完值,直接輸出即可。需要說明的是,這裡需要事先聲明一個數組用來儲存每一位的取值。當輸出完畢後,如果最低位已經遍曆完所有的位元,則回朔到上一層,修改次高位的值,以此類推,直到最高位遍曆完所有的進位數。
程式如下:
package com.majing.test;public class test1 {public static void main(String[] args) {print(3,2);}private static int[] array=null;public static void print(int n,int b){assert n>0 && b>1;if(null==array){array=new int[n];}print(n,n,b);}public static void print(int n,int cur,int b){if(cur<=0){for(int i=n-1;i>=0;i--){System.out.print(array[i]);}System.out.println();return;}for(int i=0;i<b;i++){array[cur-1]=i;print(n,cur-1,b);}}}
測試結果如下所示:
000001010011100101110111
(2)給定N個數,輸出這N個數的全排列(N個數各不相同)
對於這個問題,我們也可以採用遞迴的方式來進行求解,假設這N個數儲存在大小為N的數組中,對於N個數的全排列,我們可以將其縮小為N-1個數的全排列,具體方法就是將這N個數都與第一個數進行交換(當然第一個數不需要交換,因為它們兩是重合的),如1與2,1與3,...,1與N分別交換,對於每一次交換都遞迴求出剩下N-1個數的全排列,這樣當1與2,1與3,...,1與N所有的組合都被遍曆完後,N個數的全排列也就全部遍曆出來了。
程式:
/** * 輸出[1-n]的N個數的全排列 */private static int[] arrayfull={1,2,3,4};public static void printfull(int[] array){assert array!=null && array.length!=0;printfull(arrayfull,arrayfull.length,0);}private static void printfull(int[] array,int n,int cur){if(cur==n){System.out.println(Arrays.toString(arrayfull));return;}for(int i=cur;i<n;i++){swap(arrayfull,cur,i);printfull(arrayfull,n,cur+1);swap(arrayfull,cur,i);}}private static void swap(int[] array,int i,int j){int tmp=array[i];array[i]=array[j];array[j]=tmp;}
運行結果如下:
[1, 2, 3, 4][1, 2, 4, 3][1, 3, 2, 4][1, 3, 4, 2][1, 4, 3, 2][1, 4, 2, 3][2, 1, 3, 4][2, 1, 4, 3][2, 3, 1, 4][2, 3, 4, 1][2, 4, 3, 1][2, 4, 1, 3][3, 2, 1, 4][3, 2, 4, 1][3, 1, 2, 4][3, 1, 4, 2][3, 4, 1, 2][3, 4, 2, 1][4, 2, 3, 1][4, 2, 1, 3][4, 3, 2, 1][4, 3, 1, 2][4, 1, 3, 2][4, 1, 2, 3]
(3)對於N個數,求出這N個數的全排列(數字可以重複)
對於這個問題,我覺得比上面的問題更加容易,只要對每一個數,將其可能的值全部遍曆一遍就可以了,這裡我們仍然採用遞迴的方式。
程式:
/** * 求N個數的全排列,可以重複 */private static int[] arrayfull2={1,2,3};public static void printfull2(int[] array){assert array!=null && array.length!=0;int[] arr=new int[array.length];printfull2(array,arr,arrayfull2.length,0);}private static void printfull2(int[] array,int[] arr,int n,int cur){if(cur==n){System.out.println(Arrays.toString(arr));return;}for(int i=0;i<n;i++){arr[cur]=array[i];printfull2(arrayfull2,arr,n,cur+1);}}
運行結果:
[1, 1, 1][1, 1, 2][1, 1, 3][1, 2, 1][1, 2, 2][1, 2, 3][1, 3, 1][1, 3, 2][1, 3, 3][2, 1, 1][2, 1, 2][2, 1, 3][2, 2, 1][2, 2, 2][2, 2, 3][2, 3, 1][2, 3, 2][2, 3, 3][3, 1, 1][3, 1, 2][3, 1, 3][3, 2, 1][3, 2, 2][3, 2, 3][3, 3, 1][3, 3, 2][3, 3, 3]
(4)未完待續...