寻找一个整数所有数字全排列的下一个数
- 储备知识
- 第一步
- 第二步
- 第三步
- JAVA实现
给出一个正整数,找出这个正整数所有数字全排列的下一个数。说通俗点就是在一个整数所包含数字的全部组合中,找到一个大于且仅大于原数的新整数。
例子:
如果输入12345,则返回12354。
如果输入12354,则返回12435。
如果输入12435,则返回12453。
为了和原数接近,我们需要尽量保持高位不变,低位在最小的范围内变换顺序。
变换顺序的范围大小,则取决于当前整数的逆序区域。
12354的逆序区域是最后两位,仅看这两位已经是当前的最大组合。
若想最接近原数,又比原数更大,必须从倒数第3位开始改变。
具体操作:我们需要从后面的逆序区域中找到大于3的最小的数字,让其和3的位置进行互换。
倒数第3位已经确定,这个时候最后两位仍然是逆序状态。我们需要把最后两位转变为顺序状态,以此保证在倒数第3位数值为4的情况下,后两位尽可能小
储备知识
如果是固定的几个数字,应该是在逆序排列的情况下最大,在顺序排列的情况下最小。
数字的顺序和逆序,是全排列中的两种极端情况。
为了和原数接近,我们需要尽量保持高位不变,低位在最小的范围内变换顺序
变换顺序的范围大小,则取决于当前整数的逆序区域。
第一步
从后向前查看逆序区域,找到逆序区域的前一位,也就是数字置换的边界。
第二步
让逆序区域的前一位和逆序区域中大于它的最小的数字交换位置。
第三步
把原来的逆序区域转为顺序状态
JAVA实现
package algorithmProblem;
import java.util.Arrays;
public class nextNumberOfTheFullArrangement {
//找数字置换的边界***************
private static int findTransformerPoint(int[] number){
for (int i= number.length-1;i>0;i--){
if(number[i]>number[i-1]){
return i;
}
}
//说明数组已经逆序
return 0;
}
//把逆序区域的前一位和逆序区域中刚刚大于它的数字交换位置
private static int[] exchangeHead(int[] number,int index){
//逆序区域的前一位:index-1
int head = number[index-1];
for (int i =number.length-1;i>0;i--){
if(head<number[i]){
number[index-1] = number[i];
number[i]=head;
break;
}
}
//交换元素后的数组
return number;
}
//把原来的逆序区域转为顺序
private static int[] reverse(int[]num,int index){
for (int i = index,j=num.length-1;i<j;i++,j--){
int temp = num[i];
num[i] = num[j];
num[j]= temp;
}
return num;
}
//传入是一个数组,得到结果再用数组输出
public static int[] findNearestNumber(int[] number){
//1. 从后向前查看逆序区域,***找到逆序区域的前一位***,也就是数字置换的边界
int index = findTransformerPoint(number);
// 如果数字置换边界是0,说明整个数组已经逆序,无法得到更大的相同数
if(index==0){
return null;
}
//2.把逆序区域的前一位和逆序区域中刚刚大于它的数字交换位置
//先复制一份
int[] numberCopy = Arrays.copyOf(number,number.length);
exchangeHead(numberCopy,index);
//把原来的逆序区域转为顺序
reverse(numberCopy,index);
return numberCopy;
}
private static void output(int[] number){
for (int i:number){
System.out.print(i);
}
System.out.println();
}
}
特别关注逆序区域的划分
测试类
public static void main(String[] args) {
int[]a = new int[]{1,2,4,3,5};
int[] newa=new int[]{};
newa= findNearestNumber(a);
output(newa);
System.out.println("打印当前数组之后的10个全排列整数");
//打印12345 之后的10个全排列整数
for (int i = 0;i<10;i++){
a = findNearestNumber(a);
output(a);
}
}