LeetCode Hot100 31.下一个排列

文章目录

题目描述

整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。

例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。

整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。

例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。

类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。

而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。

给你一个整数数组 nums ,找出 nums 的下一个排列。

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

示例 1:

输入:nums = [1,2,3]

输出:[1,3,2]

示例 2:

输入:nums = [3,2,1]

输出:[1,2,3]

示例 3:

输入:nums = [1,1,5]

输出:[1,5,1]

提示:

1 <= nums.length <= 100

0 <= nums[i] <= 100

题目解法

本题实质上使用的解法应当是双指针+贪心算法的应用。

本题的重点在于位置带来的权重与数字大小带来的权值之间的平衡。

要获得下一个最大排列,最简单的想法就是把前面的"小数"与后面的"大数"相交换。同时小数越靠右越好,大数越小越好。

这是因为小数越靠右权重就越小,所以这个位置换上大数后影响也就越小。

大数越小,造成的影响也就越小。

有了这个思想,我们令大数指针为 i ,小数指针为 j。大数指针从右向左寻找,这是因为为了让大数尽量靠近右边。

当局部出现从左向右递减数列时,我们必须跳过。

这是因为局部此时已经是最大情况了,想要更大不可能。只能跳过。

所以得到大数指针如下:

java 复制代码
int i = nums.length - 2;
        while (i >= 0 && nums[i] >= nums[i + 1]) {
            i--;
        }

但是如果整个数组都是递减数组,那么 i 的值将会是-1。这种情况直接翻转整个数组即可。因此在此处用 if 划分出不同的情况。

当 i >= 0时,就说明此时的地址指针有效。我们再去寻找小数指针 j 。

小数指针同样从右向左寻找。一是因为右边位置权值小,二是因为右边的大数指针刚刚经历过递减数列,找到小数的循环次数少。

java 复制代码
if (i >= 0) {
            int j = 0;
            while (j < nums.length && nums[i] >= nums[j]) {
                j++;
            }
            swap(nums, i, j);
        }

找到之后交换大数和小数的位置。

然后反向原大数指针位置后一位置的所有数列。这是因为后面跳过的都是递减数列,reverse之后变成了递增数列,整体变小。

完整代码

java 复制代码
class Solution {
    public void nextPermutation(int[] nums) {
        int i = nums.length - 2;
        while (i >= 0 && nums[i] >= nums[i + 1]) {
            i--;
        }
        if (i >= 0) {
            int j = nums.length - 1;
            while (j >= 0 && nums[i] >= nums[j]) {
                j--;
            }
            swap(nums, i, j);
        }
        reverse(nums, i + 1);
    }

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

    public void reverse(int[] nums, int start) {
        int left = start, right = nums.length - 1;
        while (left < right) {
            swap(nums, left, right);
            left++;
            right--;
        }
    }
}
相关推荐
Felven40 分钟前
A. Everybody Likes Good Arrays!
数据结构·算法
AI_RSER2 小时前
基于 Google Earth Engine 的南京江宁区土地利用分类(K-Means 聚类)
算法·机器学习·分类·kmeans·聚类·遥感·gee
Small踢倒coffee_氕氘氚2 小时前
是否应该禁止危险运动论文
经验分享·笔记·算法·灌灌灌灌
编码小笨猪3 小时前
技术面试一面标准流程
面试·职场和发展
京东云开发者3 小时前
行稳、致远 | 技术驱动下的思考感悟
算法
Dignity_呱3 小时前
记一次手撕算法面试
前端·算法·面试
CodeJourney.3 小时前
深度探索:DeepSeek赋能WPS图表绘制
数据库·人工智能·算法·信息可视化·excel
陈奕昆3 小时前
6.1腾讯技术岗2025面试趋势前瞻:大模型、云原生与安全隐私新动向
算法·安全·云原生·面试·腾讯
ゞ 正在缓冲99%…4 小时前
leetcode66.加一
java·数据结构·算法
Aqua Cheng.4 小时前
华为开发岗暑期实习笔试(2025年4月16日)
java·算法·华为·动态规划