美文网首页
0031. 下一个排列

0031. 下一个排列

作者: 蓝笔头 | 来源:发表于2021-08-18 09:39 被阅读0次

题目地址

https://leetcode-cn.com/problems/next-permutation/

题目描述

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

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

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

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

题解

找规律(1)

从右往左遍历,找到一个可以用来交换的位置——当前位置的数,存在右边的数比当前位置的数大。

class Solution {
    public void nextPermutation(int[] nums) {
        int length = nums.length;

        for (int i = length - 1; i >= 0; -- i) {
            int minValue = Integer.MAX_VALUE;
            int swapIndex = -1;
            for (int j = i + 1; j < length; ++ j) {
                // 找到 [i+1, ..., length-1] 列表中大于 nums[i] 中的数里面最小的一个
                // 如果一样大,则选择靠后的一个
                if (nums[i] < nums[j] && minValue >= nums[j]) {
                    minValue = nums[j];
                    swapIndex = j;
                }
            }

            if (swapIndex != -1) {
                swap(nums, i, swapIndex);
                // 需要重排序后面的数
                Arrays.sort(nums, i + 1, length);
                return;
            }
        }
        
        // 如果没有找到,说明不存在下一个更大的排列,将数字重新排列为最小的排列
        Arrays.sort(nums, 0, length);
    }

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

最坏的时间复杂度为:O(n^2)

找规律(2):剪枝

从右向左遍历,找到第一个 nums[index] < nums[index+1] 的位置 index
nums[index] 就是需要和后面的数字进行交换的数。

class Solution {
    public void nextPermutation(int[] nums) {
        int length = nums.length;

        int i = getFirstSwapIndex(nums);
        int minValue = Integer.MAX_VALUE;
        int swapIndex = -1;
        for (int j = i + 1; j < length; ++ j) {
            // 找到 [i+1, ..., length-1] 列表中大于 nums[i] 中的数里面最小的一个
            // 如果一样大,则选择靠后的一个
            if (nums[i] < nums[j] && minValue >= nums[j]) {
                minValue = nums[j];
                swapIndex = j;
            }
        }

        if (swapIndex != -1) {
            swap(nums, i, swapIndex);
            Arrays.sort(nums, i + 1, length);
            return;
        }
        
        // 如果没有找到,说明不存在下一个更大的排列,将数字重新排列为最小的排列
        Arrays.sort(nums, 0, length);
    }

    public int getFirstSwapIndex(int[] nums) {
        // 从右向左遍历
        // 找到第一个 nums[index] < nums[index+1] 的位置 index
        int index = nums.length - 2;
        while (index > 0 && nums[index] >= nums[index+1]) {
            index--;
        }
        return index < 0 ? 0 : index;
    }

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

时间复杂度为:O(n)

执行时间没有很大的差异,应该是执行用例不够完善的原因。

相关文章

  • 0031. 下一个排列

    题目地址 https://leetcode-cn.com/problems/next-permutation/[h...

  • 全排列系列总结

    一. 找到下一个全排列 这是给定一个排列,找它的下一个全排列 给出一个数字排列中按字典序排列的下一个更大的排列。如...

  • LeetCode 31. 下一个排列 | Python

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

  • 31. 下一个排列

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

  • 31-下一个排列

    下一个排列 题目 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。 如果不存在...

  • LeetCode每日一题: 31. 下一个排列

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

  • 31. 下一个排列

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

  • 下一个排列

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

  • 下一个排列

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

  • 【LeetCode】排列问题

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

网友评论

      本文标题:0031. 下一个排列

      本文链接:https://www.haomeiwen.com/subject/nslvbltx.html