尋找全排列的下一個數,這題的意思就是:
給出一個數,求出由每位數形成的所有全排列中,大於此數的最小值
注:我們給出的這個數每位都不同
具體的算法描述如下:
/**
*
* 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));
}
}
}