LeetCode 31.下一个排列

该博客详细解析了LeetCode中寻找下一个排列的问题,通过原地修改数组实现。思路包括特殊情况处理、如何找到最小的大数以及如何反转部分序列以达到下一个排列。代码展示了如何在给定的整数数组中找到并生成下一个更大的排列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

题目描述:

 

 思路:

        1.特殊情况:给定的序列是降序排列,如[3, 2, 1];那么结果直接反转为[1,2,3]

        2.题目要求 原地修改   -》 使用给的nums数组进行元素交换

        下一个排列要满足:比当前序列尽可能的小    -》 很明显应该从后面依次向前挪动

                a. 比当前序列小:从后往前查找(begin, end), 有 begin < i < j < end,满足nums[i] < nums[j], 交换两个数,结果一定小于原来的序列;如 12345 -> 12354

                b. 尽可能的小:根据情况a找到大数和小数下标 i, j, 在区间[j, end)中从后往前查找第一个大于nums[i]的数 k, 交换这两个数,然后将新序列的[j, end)区间进行反转

                如: 124653 -》 125643 符合;

可证:[j, end) 单调递减的,因此nums[k](大于nums[i]的第一个数)与nums[i]交换后,一定也满足[j, end)单调递减,且 nums[i]的值一定大于原来的值 

题解参考:https://leetcode-cn.com/problems/next-permutation/solution/xia-yi-ge-pai-lie-suan-fa-xiang-jie-si-lu-tui-dao-/

 

代码:

 /*
    从就往前遍历,找到第一个升序的相邻数列,记为i,j, 得区间[j, end)
    在[j, end)区间中从后往前找到第一个nums[k] > nums[i], 交换,然后[j, end)升序
  */
    public void nextPermutation(int[] nums) {
        if (nums.length == 1) return;
        int len = nums.length;
        boolean flag = false;
        for (int i = len - 1; i > 0; i--) {
            if (nums[i - 1] < nums[i]) {
                flag = true;
                for (int j = len - 1; j >= i; i--) {
                    if (nums[j] > nums[i - 1]) {
                        swap(nums, i - 1, j);
                        break;
                    }
                }
                reverse(nums, i, len - 1);
            }
            if (flag) break;
        }
        if (!flag) {
            reverse(nums, 0, len - 1);
        }
    }

    private void reverse(int[] nums, int begin, int end) {
        while (begin <= end) {
            swap(nums, begin, end);
            begin ++; end --;
        }
    }

    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值