读书笔记——漫画算法(6) 寻找全排列的下一个数

寻找全排列的下一个数,这题的意思就是:

给出一个数,求出由每位数形成的所有全排列中,大于此数的最小值


注:我们给出的这个数每位都不同

具体的算法描述如下:

/**
* 
* 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));
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章