31.下一个排列

题目描述:

实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。

示例:

以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,31,3,2
3,2,11,2,3
1,1,51,5,1

解答:

public static void nextPermutation(int[] nums) {
        /*
         * 1.判断按照字典序有木有下一个,如果完全降序就没有下一个 
         * 2.如何判断有木有下一个呢?只要存在a[i-1] < a[i]的升序结构,就有,
         * 而且我们应该从右往左找,一旦找到,因为这样才是真正下一个 
         * 3.当发现a[i-1] < a[i]的结构时,从在[i,∞]中找到最接近a[i-1]并且又大于a[i-1]的数字,由于降序,从右往左遍历即可得到k
         * 4.然后交换a[i-1]与a[k],然后对[i, ∞]排序即可, 排序只需要首尾不停交换即可,因为已经是降序
         * 上面说的很抽象,还是需要拿一些例子思考才行,比如[0,5,4,3,2,1],下一个是[1,0,2,3,4,5]
         */
        int i = nums.length - 2;
        // 从右往左找到第一个逆序数
        while (i >= 0 && nums[i] >= nums[i + 1]) {
            i--;
        }
        // 第一个逆序元素与大于这个逆序数的值交换
        if (i >= 0) {
            int j = nums.length - 1;
            while (j >= 0 && nums[j] <= nums[i]) {
                j--;
            }
            swap(nums, i, j);
        }
        // 即使没找到第一个逆序数【nums已降序】,将数组逆序排序【升序】
        // 交换之后,需要将交换后的第一个逆序元素之后的元素进行升序排序【因为原先已经是降序】
        reverse(nums, i + 1);
    }

    // 将降序数组反转为升序数组的方法1,left++;right--;
    private static void reverse(int[] nums, int start) {
        // 将降序数组反转为升序数组的方法,left++,mid=sum/2,start和end不确定
        // private static void reverse3(int[] nums, int start,int end) : int i = start, j = end;
        int i = start, j = nums.length - 1;
        while (i < j) {
            swap(nums, i, j);
            j--;
            i++;
        }
    }
    // 将降序数组反转为升序数组的方法2,left++,mid=sum/2
    private static void reverse1(int[] nums, int start) {
        // 将降序数组反转为升序数组的方法,left++,mid=sum/2,start和end不确定
        // private static void reverse4(int[] nums, int start,int end) : int sum = start + end + 1;
        int sum = start + nums.length - 1;
        int mid = sum / 2;
        for (; start <= mid; start++) {
            int tmp = nums[start];
            nums[start] = nums[sum  - start];
            nums[sum  - start] = tmp;
        }
    }
    private static void swap(int[] nums, int i, int j) {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }

注意:

1.逆序的两种方式【right和mid】
2.mid中,sum为start + nums.length-1时,start<=mid【如果sum=2】

你可能感兴趣的:(31.下一个排列)