1. 理解下一个排列问题
在解决LeetCode第31题"下一个排列"之前,我们需要先理解什么是排列以及"下一个排列"的定义。排列是指将一组元素按照特定顺序排列的方式。对于一个包含n个不同元素的集合,总共有n!种不同的排列方式。
1.1 字典序排列
字典序排列是指按照字母表顺序排列的方式。对于数字排列来说,可以类比为数字组成的字符串按字典顺序排列。例如:
- [1,2,3] < [1,3,2] < [2,1,3] < [2,3,1] < [3,1,2] < [3,2,1]
1.2 下一个排列的定义
给定一个排列,它的下一个排列是指在字典序中刚好比它大的那个排列。如果没有更大的排列(即已经是字典序最大的排列),则返回字典序最小的排列(即第一个排列)。
例如:
- [1,2,3]的下一个排列是[1,3,2]
- [3,2,1]的下一个排列是[1,2,3](因为它是最后一个排列)
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 算法思路解析
2.1 直观思考
要找到下一个更大的排列,我们需要找到能够使排列变大的最小变化。这类似于我们日常生活中的数字:要找到比123大的最小数字是132,而不是213或321。
2.2 关键观察
通过观察字典序排列的规律,我们可以发现几个重要特征:
- 排列的"增长"总是从右向左发生的
- 要找到下一个更大的排列,需要找到第一个可以"增大"的位置
- 增大后,后面的部分应该尽可能小
2.3 四步算法
基于这些观察,我们可以将算法分解为四个步骤:
- 从后向前找第一个降序点:找到第一个满足nums[i] < nums[i+1]的位置i
- 从后向前找第一个比nums[i]大的数:找到位置j,使得nums[j] > nums[i]
- 交换nums[i]和nums[j]
- 反转i+1到末尾的子数组
3. 详细步骤解析
3.1 第一步:寻找拐点i
我们需要从数组末尾开始向前查找,找到第一个满足nums[i] < nums[i+1]的位置i。这个位置i就是我们能够增大排列的"拐点"。
为什么从后向前查找?
- 因为字典序的变化总是从低位开始的
- 我们需要找到最右边的可以增大的位置,这样才能保证变化是最小的
特殊情况处理:
- 如果找不到这样
