31. 下一个排列

129 阅读1分钟

思路

  • 找到一对「较小数」与「较大数」的组合为与,满足「较小数」尽量靠右,而「较大数」尽可能小。
  • 从后往前找到第一个降序的数字,作为较大数,替换他
    • 这个数字后面为升序,所以,从这个位置开始往后构成的数字已经是最大
  • 从后往前找第一个比替换数大的数字,作为较小数,swap
  • 后段必为降序,reverse一下再

image.png

class Solution {
    public void nextPermutation(int[] nums) {
        int i = nums.length - 1;
        // 从后往前找到第一个降序的数字
        while (i - 1 >= 0 && nums[i - 1] >= nums[i]) {
               i--; 
        }
        if (i > 0) { // 处理 3,2,1这种情况,直接reverse
            int j = nums.length - 1;
            // 再从后往前找第一个比替换数大的数字
            while (j > i - 1 && nums[j] <= nums[i - 1]) {
                j--;
            }
            swap(nums, i - 1, j);
        }
        reverse(nums, i, nums.length - 1);
    }
    
    public void swap(int[] nums, int m, int n) {
        int tmp = nums[m];
        nums[m] = nums[n];
        nums[n] = tmp;
    }

    public void reverse(int[] nums, int m, int n) {
        int i = m, j = n;
        while (i < j) {
            swap(nums, i, j);
            i++;
            j--;
        }
    }
}