云小杰

相对于绝对成功的汲汲渴求,越无杂质的奔赴,越是动人。

要一个黄昏, 满是风, 和正在落下的夕阳。如此, 足够我爱这破碎泥泞的人间。


Download the theme

下一个排列

下一个排列

题目描述

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

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

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

示例 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]

方法

具体地,我们这样描述该算法,对于长度为 n 的排列 a

  • 首先从后向前查找第一个顺序对 (i,i+1),满足 a[i] < a[i+1]。这样「较小数」即为 a[i]。此时 [i+1,n) 必然是下降序列。

  • 如果找到了顺序对,那么在区间 [i+1,n) 中从后向前查找第一个元素 j 满足 a[i] < a[j]。这样「较大数」即为 a[j]

  • 交换 a[i]a[j],此时可以证明区间 [i+1,n) 必为降序。我们可以直接使用双指针反转区间 [i+1,n) 使其变为升序,而无需对该区间进行排序

class Solution {
    public void nextPermutation(int[] nums) {
        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[i] >= nums[j]) {
                j--;
            }
            swap(nums, i, j);
        }
        reverse(nums, i + 1);
    }

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

    public void reverse(int[] nums, int start) {
        int left = start, right = nums.length - 1;
        while (left < right) {
            swap(nums, left, right);
            left++;
            right--;
        }
    }
}
最近的文章

仅仅反转字母

917. 仅仅反转字母题目描述给你一个字符串 s ,根据下述规则反转字符串: 所有非英文字母保留在原有位置。 所有英文字母(小写或大写)位置反转。返回反转后的 s 。示例 1:输入:s = "ab-cd"输出:"dc-ba"示例 2:输入:s = "a-bC-dEf-ghIj"输出:"j-Ih-gfE-dCba"示例 3:输入:s = "Test1ng-Leet=code-Q!"输出:"Qedo1ct-eeLg=ntse-T!"方法:双指针​ 整体而言,这个题目还是比较简单的,双指针...…

继续阅读
更早的文章

SimpleMemory博客园皮肤

SimpleMemory博客园皮肤 1. 声明 2. 安装 SimpleMemory博客园皮肤1. 声明这个主题是一位大佬做的。大佬博客园地址:https://github.com/BNDong/Cnblogs-Theme-SimpleMemory。大佬Github地址:https://www.cnblogs.com/BNDong。2. 安装 申请JS权限 博客皮肤选择SimpleMemory ...…

Blog继续阅读