LeetCode──下一个排列(31)

六眼飞鱼酱① 提交于 2020-01-27 05:45:26

题目描述

实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
8,4,7,6,5,3,1 → 8,5,1,3,4,6,7

思路

1. 从后向前遍历,判断当前数组是否为降序排列
2. 已为降序排列,说明不存在下一个更大的数,则 i 为 -1,直接反转0 - (len - 1)
3. 找到第一个num[i] < num[i + 1]的元素
4. 此时 i 必定 >= 0,然后继续从后向前,寻找第一个比num[i]大的元素,与num[i]进行交换
5. 反转 i 之后的元素
比如

num 8 4 7 6 5 3 1
下标 0 1 2 3 4 5 6
num[i] < num[i + 1] i
num[i] < num[j] j
swap(num, i, j) 8 5 7 6 4 3 1
reverse(num, i + 1, len - 1) 8 5 1 3 4 6 7

代码:

class Solution {
    public void nextPermutation(int[] nums) {
        int i = nums.length - 2;
        //寻找第一个num[i] < num[i + 1]的元素
        while(i >= 0 && nums[i + 1] <= nums[i]){
            --i;
        }
        //数组大小大于0,需要寻找下一个数
        if(i >= 0){
            int j = nums.length - 1;
            //从后向前,寻找第一个比num[i]大的元素
            while(j > i && nums[j] <= nums[i]){
                --j;
            }
            //交换
            swap(nums, i, j);
        }
        //反转i之后的元素
        reverse(nums, i + 1);
    }

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

    //交换
    public void swap(int nums[], int i, int j){
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!