下一个排列

题目:
实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。

如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。

必须 原地 修改,只允许使用额外常数空间。

解题思路:
找下一个排列的方法:先找出最大的索引 k 满足 nums[k] < nums[k+1],如果不存在,就翻转整个数组;再找出另一个最大索引 l 满足 nums[l] > nums[k];交换 nums[l] 和 nums[k];最后翻转 nums[k+1:len - 1]。

示例 1:

输入:nums = [1,2,3]
输出:[1,3,2]
示例 2:

输入:nums = [3,2,1]
输出:[1,2,3]
示例 3:

输入:nums = [1,1,5]
输出:[1,5,1]
示例 4:

输入:nums = [1]
输出:[1]

class Solution {
    public void nextPermutation(int[] nums) {
        // 从后往前找到第一个 a[i] < a[i + 1]
        int len = nums.length;
        int cur = len - 2;
        for(; cur >= 0; cur--) {
            if(nums[cur] < nums[cur + 1]) {
                break;
            }
        }
        
        // 如果没有找到a[i] 说明数组已经是升序排列 直接翻转即可
        if(cur < 0) {
            reverse(nums, 0, len - 1);
            return ;
        }
        
        // 从后往前找到第一个 > a[i]的数
        int idx = len - 1;
        for(; idx >= 0; idx--) {
            if(nums[idx] > nums[cur]) {
                break;
            }
        }
        
        // 交换
        swap(nums, cur, idx);
        
        // 反转[i + 1, n - 1]
        reverse(nums, cur + 1, len - 1);
    }
    
    private void swap(int[] nums, int i, int j) {
        int t = nums[i];
        nums[i] = nums[j];
        nums[j] = t;
    }
    
    private void reverse(int[] nums, int i, int j) {
        while(i < j) {
            swap(nums, i, j);
            i++;
            j--;
        }
    }
}