下一个排列(Leetcode31)解读

本题代码来自Leetcode官方,个人对其理解后,生成自己的注解,以便更好的让读者理解。如有侵权,立即删除!

public class Main31 {

    public static void main(String[] args) {
        int[] arr = new int[]{9, 5, 3, 1};
        nextPermutation(arr);
    }

    /**
     * 核心思想:给定一个降序则该序列没有可能有下一个更大的排列;
     * 1.从给定数组的右侧扫描出第一个a[i-1]<a[i]; (违背了核心思想,所以处理)
     * 2.对a[i-1]固定位置,从其右侧(从右到左)找出第一个比a[i-1]大的数字a[j];
     * 3.交换a[i-1]和a[j]的值。此时a[i-1]位置是下一个更大元素的首位,也是未交换之前a[i-1]到右侧最后一位组成数的下一个比起大的数的首位;
     * 4.将a[i-1]右侧重新排列为最小(升序,之前的降序);此时,构成的数是原数下一个比其大的数;
     * @param nums
     */
    public static void nextPermutation(int[] nums) {
        int i = nums.length-1;  //倒数第1个元素下标

        while(i-1 >= 0 && nums[i] <= nums[i-1]){ /*确定nums[i-1]的位置,即nums[i-1]<nums[i],简化为确定i-1的位置*/
            i--;
        }
        if(i-1 >= 0){  /*如果i位置还在数组中,即nums[i]<nums[i+1]*/  /*i不在数组的情况就是遇到了一降序数组,直接反转让其成一个最小数列*/
            int j = nums.length-1;   /*定位j到i的右侧区域的最右侧*/
            while(j >= 0 && nums[j] <= nums[i-1]){  /*找到nums[j]第一次大于nums[i-1]的位置,此时要满足j也要在数组中(当然,j肯定在数组中)*/
                j--;   /*j停下来的位置就是第一次大于nums[i-1]的位置说*/
            }
            swap(nums,i-1,j);  /*交换nums[i-1],nums[j]的值*/
        }
        reverse(nums,i); /*反转i右侧的降序,转变为升序*/
    }

    private static void reverse(int[] nums, int start) {
        int i = start;
        int j = nums.length-1;
        while (i < j){
            swap(nums,i,j);
            i++;
            j--;
        }
    }

    private static void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

猜你喜欢

转载自www.cnblogs.com/startelk/p/11305980.html