一個算法命題:給定字符串S[0…N-1],設計算法,枚舉S的全排列。如:123,全排列就是:123,132,213,231,312,321
個人愚昧,搞了一天半,才終於把字典排列搞出來,看不到大神寫的代碼,我的代碼還有很多優化之處,先記錄下,遞歸現在還是有點蒙。
java代碼:遞歸實現(考慮有重復的字符)
以字符串1234為例:
1 – 234
2 – 134
3 – 214
4 – 231
如何保證不遺漏: 每次遞歸前,保證1234的順序不變。
1 package stringtest; 2 import java.util.ArrayList; 3 import java.util.Collections; 4 5 /**題目描述 6 輸入一個字符串,按字典序打印出該字符串中字符的所有排列。 7 例如輸入字符串abc,則打印出由字符a,b,c所能排列出來的所有字符串abc,acb,bac,bca,cab和cba。 8 輸入描述: 9 輸入一個字符串,長度不超過9(可能有字符重復),字符只包括大小寫字母。 10 * 11 * 12 * @author Administrator 13 * 14 */ 15 public class FullArray { 16 17 public static void main(String[] args) { 18 FullArray fa = new FullArray(); 19 String str = "abc"; 20 ArrayList<String> arrayList = fa.Permutation(str); 21 for (String string : arrayList) { 22 System.out.println(string); 23 } 24 } 25 26 /** 27 * 思路:利用遞歸的思想。來實現 28 * 先讓a第一位:剩余bcd做全排列 29 * 先讓b第一位:剩余acd做全排列 30 * 先讓c第一位:剩余abc做全排列 31 * 先讓d第一位:剩余abc做全排列 32 * 33 * @param str 34 * @return 35 */ 36 ArrayList<String> list = new ArrayList<>(); 37 public ArrayList<String> Permutation(String str) { 38 char[] array = str.toCharArray(); 39 permutaionTest(array,0,str.length()-1); 40 Collections.sort(list); 41 return list; 42 } 43 44 public void permutaionTest(char[] array,int start,int end){ 45 //遞歸退出條件 46 if(array.length<1){ 47 return; 48 } 49 //如果start和end不相等,說明完成一次排序 50 if(start==end){ 51 String val = new String(array); 52 //這里也是判斷元素重復情況(方式一) 53 if (!list.contains(val)) 54 list.add(val); 55 }else{ 56 //回溯法,每次固定一個元素在最前面,后面元素進行全排列 57 for (int i = start; i <= end; i++) { 58 59 //考慮有重復元素的情況(方式二) 60 boolean flag = true; 61 for (int j = start; j < i; j++) { 62 if(array[j] == array[i]){//這里吧i換成end也行 63 flag = false; 64 } 65 } 66 67 //有重復元素就跳過大循環,下一個比較 68 if(flag){ 69 swap(array,start,i); 70 permutaionTest(array,start+1,end); 71 swap(array,i,start); 72 } 73 } 74 } 75 } 76 77 private void swap(char[] array, int start, int i) { 78 if(start!=i){ 79 char tmp = array[start]; 80 array[start] = array[i]; 81 array[i] = tmp; 82 } 83 } 84 }
java代碼:字典序排列(考慮有重復的字符)
全排列的非遞歸算法:整理成算法語 步驟:后找、小大、交換、翻轉——
后找:字符串中最后一個升序的位置i,即S[k]>S[k+1](k>i),S[i]<S[i+1];
查找(小大):S[i+1…N-1]中比Ai大的最小值(補充:根據規律,好像只要從右往左找第一個比Ai大的值就行。)
交換:Si,Sj;
翻轉:S[i+1…N-1]
個人總結:以926520為例
①:字符串從后往前找,找到第一個降序的值為2,位置為1
②:然后找出2和后面比2大的數的最小值為5(補充:從右往左找第一個比2大的值為5。)
③:2和找出的5進行位置交換
④:把2后面所有的數進行翻轉
最后大功告成:
第一步:先把字符串進行全排序
1 package com.qyzx.string; 2 3 import java.util.ArrayList; 4 import java.util.Arrays; 5 6 public class AllArray2 { 7 8 public static void main(String[] args) { 9 String str = "1212"; 10 char[] arr = str.toCharArray(); 11 //先對數組進行重小到大進行排序 12 Arrays.sort(arr); 13 fullArray(arr,0,arr.length-1); 14 } 15 16 /** 17 * 該方法是對字符串進行全排列 18 * 19 * @param arr 20 * @param i 21 * @param j 22 */ 23 private static boolean fullArray(char[] arr, int start, int end) { 24 if(end<1){ 25 return true; 26 } 27 while(true){ 28 System.out.println(arr); 29 //①:從后往前找,找出第一個降序的值 30 int first = end; 31 for (int i = end; i >= 1; i--) { 32 if(arr[i-1]<arr[i]){ 33 first = i-1; 34 break; 35 }else if(i==1){ 36 //說明已經排好序了,沒有降序的值。 37 return false; 38 } 39 } 40 // System.out.println("第一個降序的值n:"+arr[first]+",first下標:"+first); 41 //②:找出first后面比first大的數 42 ArrayList<Integer> list = new ArrayList<>(); 43 for (int i = first+1; i < end+1; i++) { 44 if(arr[first]<arr[i]){ 45 list.add(i); 46 } 47 } 48 //比first大的數的最小值 49 int min = list.get(0); 50 for (int i = 1; i < list.size(); i++) { 51 if(arr[min]>arr[list.get(i)]){ 52 min = list.get(i); 53 } 54 } 55 // System.out.println("比n大的最小值m:"+arr[min]+",min下標:"+min); 56 //③:然后交換min和first的位置 57 swap(arr,min,first); 58 //④:因為交換了位置,所以現在的min就是之前的first,把min后面所有的字符串進行反轉 59 // System.out.println("n后面數字進行翻轉前:"+String.valueOf(arr)); 60 resver(arr,first+1,end); 61 // System.out.println("n后面數字進行翻轉后:"+String.valueOf(arr)); 62 } 63 } 64 65 //實現arr數組的s位置到end位置的翻轉 66 private static void resver(char[] arr, int start, int end) { 67 while(start<end){ 68 //可以把最后賦值給前面 69 char temp1 = arr[start]; 70 arr[start++] = arr[end]; 71 arr[end--] = temp1; 72 } 73 } 74 75 //進行元素之間交換位置 76 public static void swap(char[] arr,int from ,int to){ 77 char s = arr[from]; 78 arr[from] = arr[to]; 79 arr[to] = s; 80 } 81 82 }
