快捷搜索: 王者荣耀 脱发

LeetCode_双指针_中等_31.下一个排列

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]

提示: 1 <= nums.length <= 100 0 <= nums[i] <= 100

2.思路

(1)双指针 思路参考该。

想得到当前排列在字典序中下一个更大的排列,则需要将前面的“小数”与后面的”大数“进行交换,并且还要保证下一个数的增加幅度最小,这样就能得到符合条件的排列。为此需要: ① 从数组后面向前找第一个升序元素对 (nums[i], nums[i + 1]),即 nums[i] < nums[i + 1],其中从后向前找是为了尽量在低位上交换,以保证下一个数增加的幅度最小; ② 在 nums[i + 1…nums.length - 1] 中从后向前查找第一个大于 nums[i] 的值 nums[j],然后交换它们的值; ③ 最后将 nums[i + 1] ~ nums[nums.length - 1] 从降序变成升序即可,由于前面已经将 nums[i] 与 nums[j] (nums[i] < nums[j]) 进行了交换,即新得到的排列已经比原来的大,但为了保证增加的幅度最小,所以需要将 nums[i] 后面的序列变成降序。

3.代码实现(Java)

//思路1————双指针
class Solution {
          
   
    public void nextPermutation(int[] nums) {
          
   
        int i = nums.length - 2;
        //从数组后面向前找第一个升序元素对(nums[i], nums[i + 1]),即 nums[i] < nums[i + 1]
        while (i >= 0 && nums[i] >= nums[i + 1]) {
          
   
            i--;
        }
        //若 i >= 0,则已经找到升序元素对
        if (i >= 0) {
          
   
            int j = nums.length - 1;
            //在 nums[i + 1...nums.length - 1] 中从后向前查找第一个大于 nums[i] 的值 nums[j]
            while (j >= 0 && nums[j] <= nums[i]) {
          
   
                j--;
            }
            //交换 nums[i] 和 nums[j] 的值
            swap(nums, i, j);
        }
        //将 nums[i + 1] ~ nums[nums.length - 1] 反转,即从降序变成升序
        reverse(nums, i + 1);
    }
    
    //将 nums[start] ~ nums[nums.length - 1]反转
    public void reverse(int nums[], int start) {
          
   
        int i = start;
        int j = nums.length - 1;
        while (i < j) {
          
   
            swap(nums, i, j);
            i++;
            j--;
        }
    }
    
    //交换 nums[i] 和 nums[j] 的值
    public void swap(int[] nums, int i, int j) {
          
   
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}
经验分享 程序员 微信小程序 职场和发展