java實現字典序算法(C++中的nextPermutation函數的java實現)

  1 //問題:給定一個正整數,求該數的下一個字典序數,即下一個全排列數,即最小的大於該數的排列數
  2 //如123 132 213 231 312 321 是一個全排列序列,那麼123的下一個字典序數就是132
  3 
  4     /*
  5     該題採用字典序算法,步驟以下:
  6       1.從後向前查看逆序區域,找到逆序區域的前一位.(所謂逆序區域即倒排的區域,如12354的逆序區域是最後兩位,即從後往前遞增的區域)
  7       2.把逆序區域的前一位和逆序區域中恰好大於它的的數字交換位置.(如13542,逆序區域中恰好大於3的是4,因此交換後獲得14532)
  8       3.把原來的逆序區域中的數轉爲順序(由於交換後的逆序區域中的數依然是倒序,因此只要用兩個指針指向逆序區域的頭尾,兩兩交換再移動指針再交換...就轉成順序了)
  9 
 10      第一步之因此這樣作是由於,如1,2,3,4,5這5個數組成的全排列中,12345是全排列中最小的數,由於其是順排,54321是全排列中最大的數,由於其是倒排,那麼如12354,
 11      其逆序區域是最後兩位,即最後兩位已經無法再大了,因此就要找到倒數第三位,將逆序區域中恰好比3大的數4和倒數第三位的數字3互換,獲得12453,(之因此要找恰好大於的是由於咱們要求
 12      的是下一個全排列數),而後再將原來的逆序區域中的數按順序排列,獲得12435,由於原來的逆序區域按順序排列後獲得的纔是下一個字典序數.
 13     * */
 14 
 15 import java.util.Arrays;
 16 import java.util.Scanner;
 17 
 18 /**
 19  * c++中的nextPermutation函數的java實現
 20  */
 21 public class NextPermutation {
 22     //將輸入的非負數轉成int數組
 23     private static int[] intToIntArray(int number) {
 24         if (number < 0) {
 25             throw new RuntimeException("輸入的數不能爲負數");
 26         }
 27         String str = String.valueOf(number);
 28         int[] numbers = new int[str.length()];
 29         for (int i = 0; i < str.length(); i++) {
 30             char c = str.charAt(i);
 31             numbers[i] = Integer.parseInt(c + "");
 32         }
 33         return numbers;
 34     }
 35 
 36     //獲取逆序區域的起始下標
 37     private static int getRevRegionHeadIndex(int[] numbers) {
 38         for (int i = numbers.length - 1; i > 0; i--) {
 39             if (numbers[i] > numbers[i - 1]) {
 40                 return i;
 41             }
 42         }
 43         return 0;
 44     }
 45 
 46     //將逆序區域的前一位數字和逆序區域中恰好大於它的數字交換
 47     private static int[] exchange(int[] numbers, int index) {
 48         for (int i = numbers.length - 1; i > index - 1; i--) {
 49             if (numbers[index - 1] < numbers[i]) {
 50                 swap(numbers, index - 1, i);
 51                 return numbers;
 52             }
 53         }
 54         return numbers;
 55     }
 56 
 57     private static void swap(int[] numbers, int i, int j) {
 58         int temp = numbers[i];
 59         numbers[i] = numbers[j];
 60         numbers[j] = temp;
 61     }
 62 
 63     //將交換後的逆序區域中的數按順序排列
 64     private static int[] reverse(int[] exchange, int index) {
 65         for (int i = index, j = exchange.length - 1; i < j; i++, j--) {
 66             swap(exchange, i, j);
 67         }
 68         return exchange;
 69     }
 70 
 71     private static int intArrayToInt(int[] reverse) {
 72         StringBuilder sb = new StringBuilder();
 73         for (int i = 0; i < reverse.length; i++) {
 74             sb.append(reverse[i]);
 75         }
 76         String str = sb.toString();
 77         int nextPermutation = Integer.parseInt(str);
 78         return nextPermutation;
 79     }
 80 
 81     //返回一個非負整數的下一個全排列數,若是已是最大了,返回它自己.
 82     public static int getNextPermutation(int number) {
 83         int[] numbers = intToIntArray(number);
 84         int revRegionHeadIndex = getRevRegionHeadIndex(numbers);
 85         if (revRegionHeadIndex == 0) {
 86             return number;
 87         }
 88         int[] exchange = exchange(numbers, revRegionHeadIndex);
 89         int[] reverse = reverse(exchange, revRegionHeadIndex);
 90         int nextPermutation = intArrayToInt(reverse);
 91         return nextPermutation;
 92     }
 93 
 94     public static void main(String[] args) {
 95         //測試
 96         try {
 97             System.out.println(NextPermutation.getNextPermutation(0));
 98             System.out.println(NextPermutation.getNextPermutation(12453));
 99             System.out.println(NextPermutation.getNextPermutation(12345));
100             System.out.println(NextPermutation.getNextPermutation(54321));
101             System.out.println(NextPermutation.getNextPermutation(12333));
102             System.out.println(NextPermutation.getNextPermutation(-12345));
103         } catch (Exception e) {
104             System.out.println("輸入的數必須是非負整數!");
105         }
106 
107          /* //使用Scanner進行測試
108         Scanner scan = new Scanner(System.in);
109         // 從鍵盤接收數據
110         System.out.println("請輸入一個非負整數:");
111         // 判斷是否還有輸入
112         while (scan.hasNext()) {
113             String str = scan.next();
114             System.out.println("您輸入的數是: " + str);
115             int nextPermutation = 0;
116             try {
117                 nextPermutation = NextPermutation.getNextPermutation(Integer.parseInt(str));
118             } catch (NumberFormatException e) {
119                 System.out.println("輸入的數必須是非負整數!");
120                 System.out.println();
121                 System.out.println("請輸入一個非負整數:");
122                 continue;
123             }
124             System.out.println("該數的下一個全排列數爲:" + nextPermutation);
125             System.out.println();
126             System.out.println("請輸入一個非負整數:");
127         }
128         scan.close();    */
129     }
130 }

 

測試結果以下所示:java

相關文章
相關標籤/搜索