31 下一个排列(分析)

1. 问题描述:

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

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/next-permutation

2. 思路分析:

① 题目还是比较好理解的,比当前数组序列大的下一个排列,一开始的时候想到时候递归的方法求解出有序的全排列,然后使用循环进行扫描匹配看下一个更大一点的排列是什么,显然这种方法是效率很低的,看了领扣的官方题解之后,发现他们的思路实在是太棒了,然后自己模仿他们写了一遍代码,可以学习一下这样的思路

② 首先他们是从数组的最右端开始扫描,找到从右向左递增的递增序列,比如官方给出的例子中,158476531的数组序列,可以知道从右边往左边扫描的过程中发现13657是递增的序列,而到4的时候则不是递增的序列了,因为4大于了7,所以这个时候循环结束,循环变量记录了4这个位置,在后面递增的序列中从右往左找到第一个比4大的位置可以知道是13657中的5对应的位置,这个时候需要将4的位置与5的位置进行互换,这样的话在高位的时候就搞定了,因为调换元素之后那么剩下来的从左到右是递增的,所以需要进行翻转,应该是从4这个位置后面进行翻转,这样形成的数字序列才是下一个更大的排列

这个可以自己使用测试用例直接在idea中进行调试,可以一步步看到代码执行过程中数组元素的变换以及变量的变化

158476531

交换4与5的位置

158576431

进行数组元素的翻转:

158513467

可以在对应的方法中打上断点,一步步点击蓝色的箭头可以看到执行的具体过程以及变量的变化

3. 代码如下:

import java.util.Scanner;
public class Solution {
    /*先是需要找到从右往左递增的序列, 这个是要debug调试运行的话会非常方便*/
    public void nextPermutation(int[] nums) {
        int i = nums.length - 2, j = nums.length - 1;
        /*找到从右往左递增的序列*/
        while(i >= 0 && nums[i] >= nums[i + 1]) --i;
        if (i >= 0){
            /*在i位置后面的有序序列中找到比i位置大的位置*/
            while (j >= 0 && nums[j] <= nums[i]) --j;
            /*j位置对应的就是在有序序列中第一个比i位置大的位置, 交换两个元素的位置*/
            swap(nums, i, j);
        }
        /*将i + 1位置的元素进行翻转即可*/
        reverse(nums, i + 1);
    }

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

    public static void swap(int[] nums, int i, int j) {
        int t = nums[i];
        nums[i] = nums[j];
        nums[j] = t;
    }
}
发布了569 篇原创文章 · 获赞 153 · 访问量 59万+

猜你喜欢

转载自blog.csdn.net/qq_39445165/article/details/105123207
今日推荐