寻找全排列的下一个数,这题的意思就是:
给出一个数,求出由每位数形成的所有全排列中,大于此数的最小值
注:我们给出的这个数每位都不同
具体的算法描述如下:
/**
*
* 1. 从后向前寻找逆序区域,并返回逆序区域的最左侧索引
* 2. 将nums[index-1]与nums区间[index, nums.length-1]中大于nums[index-1]的最小元素进行位置交换
* 3. 将数组nums区间[index, nums.length-1]逆序
*
* 举个例子:12354
* 1. 找到逆序区域123|54| ,最左侧索引index = 3
* 2. 将3与4进行交换,得到124|53这样保证最高位能够最小
* 3. 将逆序区间顺序得到:124|35
*/
算法实现如下:
首先定义一个抽象类,方便表示整个算法的流程:
public abstract class TemplateFindNearestNumber {
protected int[] arr;
private TemplateFindNearestNumber() { }
TemplateFindNearestNumber(int[] arr) {
Objects.requireNonNull(arr);
this.arr = arr;
}
/**
* 1. 从后向前寻找逆序区域,并返回逆序区域的最左侧索引
* 2. 将nums[index-1]与nums区间[index, nums.length-1]中大于nums[index-1]的最小元素进行位置交换
* 3. 将数组nums区间[index, nums.length-1]逆序
* @return
*/
public int[] findNearestNumber() {
int index = findReversedOrderBorderIndex(arr);
if(index == 0) {
return null;
}
int[] copyNums = Arrays.copyOf(arr, arr.length);
exchangeHead(copyNums, index);
reverse(copyNums, index);
return copyNums;
}
/**
* 从后向前寻找逆序区域,并返回逆序区域的最左侧索引
* @param nums
* @return
*/
protected abstract int findReversedOrderBorderIndex(int[] nums);
/**
* 将nums[index-1]与nums区间[index, nums.length-1]中
* 大于nums[index-1]的最小元素进行位置交换
* @param nums
* @param index
*/
protected abstract void exchangeHead(int[] nums, int index);
/**
* 将数组nums区间[index, nums.length-1]逆序
* @param nums
* @param index
*/
protected abstract void reverse(int[] nums, int index);
}
再定义核心的算法实现,其中最后的main函数,对整个算法进行测试
public class FindNearestNumber extends TemplateFindNearestNumber {
public FindNearestNumber(int[] arr) {
super(arr);
}
@Override
public int findReversedOrderBorderIndex(int[] nums) {
int index = nums.length-1;
while(index > 0 && nums[index-1] >= nums[index]) {
index--;
}
return index;
}
@Override
protected void exchangeHead(int[] nums, int index) {
int num = nums[index-1];
for(int i = nums.length-1 ; i >= index ; i--) {
if(nums[i] > num) {
swap(nums, index-1, i);
break;
}
}
}
@Override
protected void reverse(int[] nums, int index) {
int t = nums.length - 1;
while(index < t) {
swap(nums, index++, t--);
}
}
private void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5 };
TemplateFindNearestNumber solution = null;
for(int i = 0 ; i < 10 ; i++) {
solution = new FindNearestNumber(arr);
arr = solution.findNearestNumber();
System.out.println(Arrays.toString(arr));
}
}
}