Looking next full array of a number (lexicographically Algorithm)

It gives a positive integer, to find all digital full positive integer arranged next to this number. Popular to say that is a combination of all integers containing numbers, find a new integer greater than and only larger than the original number. For example:
  • If you enter: 12345, 12354 Returns
  • If you enter: 12354, 12435 Returns
  • If you enter: 12435, 12453 Returns
Ideas:
Lexicographical algorithm:
  1. View from back to front reverse area, find the area of ​​a former reverse order, as a digital replacement boundary;
    1. Reverse zone means: size of the figures (from left to right) will be sorted from largest to smallest.
    2. So looking from right to left, the first one on the right is greater than the value of the position to the left, then the right side of this position is the starting point for reverse zones.
  2. From right to left, to find the starting point is greater than the area of ​​the front reverse [A] a minimum number B from the reverse zone, the A, B exchange position
    1. Because the size of the figures (from right to left) reverse zones will be sorted from small to large, so look just right to left, the first is greater than A, it must also reverse domain is greater than the minimum number of A's.
    2. So, to traverse from right to left to find the first number is greater than A, you can directly exchange location, exit sequential.
  3. Reverse into the original sequential state region;
    1. Similarly, since the size of the figures (from right to left) will reverse sorting zone is from small to large, so long as both ends of the reverse region, head and tail value exchange twenty-two
 
For example: 1736542, reverse area: 6542, then the starting point is the reverse zone 6, then the switching positions 3 and 4, becomes: 1,746,532, the reverse sequential state into regions: 1742356.
 
  Code:
 1 package blogSrc;
 2 
 3 import java.util.Arrays;
 4 
 5 /**
 6  * 寻找全排列的下一个数
 7  * 给出一个正整数,找出这个正整数所有数字全排列的下一个数。通俗的说就是在一个整数所包含数字的全部组合中,找到一个大于且仅大于原数的新整数。举例:
 8  * 如果输入:12345,则返回12354
 9  * 如果输入:12354,则返回12435
10  * 如果输入:12435,则返回12453
11  *
12  * 思路:
13  * 从后向前查看逆序区(数字从大到小排序),找到逆序区域的前一位,作为数字置换的边界;
14  * 让逆序区域的前一位和逆序区域中大于它的最小的数字交换位置;
15  * 把原来的逆序区域转为顺序状态;
16  * 举例: 12354,逆序区域:54,那么数字置换的边界就是3,将3和4交换位置,变为:12453,将逆序区域转为顺序状态:12435。
17  */
18 
19 public class FindNearestNumber {
20 
21     public static void main(String[] args){
22         int[] numArr = {1,7,3,6,5,4,2};
23         int[] copyArr = Arrays.copyOf(numArr,numArr.length);
24         int[] result = new FindNearestNumber().findNearestNumber(copyArr);
25         System.out.println("原始的数组:" + Arrays.toString(numArr));
26         System.out.println("处理后数组:" +Arrays.toString(result));
27     }
28 
29     public int[] findNearestNumber(int[] numArr){
30         int borderIndex = getReverseBorderIndex(numArr);
31         //如果borderIndex=0,说明这个那个数组已经逆序,无法得到更大的相同数字组成的整数
32         if(borderIndex == 0){
33             return new int[0];
34         }
35         int[] newNumArr = exchangePosition(numArr,borderIndex);
36         int[] result = changeReverse(newNumArr,borderIndex);
37         return result;
38     }
39 
40 
41     /**
42      * 从后向前,找到逆序区域边界点。
43      * 逆序区是指:数字大小(从左到右)排序一定会是从大到小。
44      * 所以从右往左找,第一个右边值大于左边值的位置,那么右边这个位置就是逆序区的起始点。
45      * @param numArr
46      * @return
47      */
48     public int  getReverseBorderIndex(int[] numArr){
49         int index = 0;
50         for (int i=numArr.length-1; i>0; i--){
51             if (numArr[i] > numArr[i-1]){
52                 return i;
53             }
54         }
55         return index;
56     }
57 
58     /**
59      * 从右向左,从逆序区中找到大于【逆序区域起始点的前一位A】的最小的数字B,将A,B交换位置。
60      * 因为逆序区的数字大小(从右到左)排序一定会是从小到大,所以只要从右向左找,第一个大于A的就一定也是逆序域中大于A的最小数字。
61      * 所以,从右向左遍历,找到第一个大于A的数字,就可以直接交换位置,退出循序。
62      * @param numArr
63      * @return
64      */
65     public int[] exchangePosition(int[] numArr, int borderIndex){
66         int borderBeforeNum = numArr[borderIndex - 1];
67         for (int i = numArr.length - 1; i > 0; i--) {
68             if (numArr[i] > borderBeforeNum) {
69                 numArr[borderIndex - 1] = numArr[i];
70                 numArr[i] = borderBeforeNum;
71                 break;
72             }
73         }
74         return numArr;
75 
76     }
77 
78      /**
79      * 把原来的逆序区域转为顺序状态.
80       * 同样的,因为逆序区的数字大小(从右到左)排序一定会是从小到大,所以只要从逆序区的两端头尾两两交换即可
81      * @param numArr
82      * @param borderIndex
83      * @return
84      */
85     public int[] changeReverse(int[] numArr, int borderIndex){
86         for (int i = borderIndex, j = numArr.length - 1; i < j; i++, j--) {
87             int temp = numArr[i];
88             numArr[i] = numArr[j];
89             numArr[j] = temp;
90         }
91         return numArr;
92 
93     }
94 }

 

 结果:

原始的数组:[1, 7, 3, 6, 5, 4, 2]
处理后数组:[1, 7, 4, 2, 3, 5, 6]

 

 

Guess you like

Origin www.cnblogs.com/zldmy/p/11517065.html