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 importjava.util.Arrays;16 importjava.util.Scanner;17
18 /**
19 * c++中的nextPermutation函数的java实现20 */
21 public classNextPermutation {22 //将输入的非负数转成int数组
23 private static int[] intToIntArray(intnumber) {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 returnnumbers;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 returni;41 }42 }43 return 0;44 }45
46 //将逆序区域的前一位数字和逆序区域中刚好大于它的数字交换
47 private static int[] exchange(int[] numbers, intindex) {48 for (int i = numbers.length - 1; i > index - 1; i--) {49 if (numbers[index - 1] 
57 private static void swap(int[] numbers, int i, intj) {58 int temp =numbers[i];59 numbers[i] =numbers[j];60 numbers[j] =temp;61 }62
63 //将交换后的逆序区域中的数按顺序排列
64 private static int[] reverse(int[] exchange, intindex) {65 for (int i = index, j = exchange.length - 1; i < j; i++, j--) {66 swap(exchange, i, j);67 }68 returnexchange;69 }70
71 private static int intArrayToInt(int[] reverse) {72 StringBuilder sb = newStringBuilder();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 returnnextPermutation;79 }80
81 //返回一个非负整数的下一个全排列数,如果已经是最大了,返回它本身.
82 public static int getNextPermutation(intnumber) {83 int[] numbers =intToIntArray(number);84 int revRegionHeadIndex =getRevRegionHeadIndex(numbers);85 if (revRegionHeadIndex == 0) {86 returnnumber;87 }88 int[] exchange =exchange(numbers, revRegionHeadIndex);89 int[] reverse =reverse(exchange, revRegionHeadIndex);90 int nextPermutation =intArrayToInt(reverse);91 returnnextPermutation;92 }93
94 public static voidmain(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 }