1. 理解排列与字典序
排列是数学中一个基础但重要的概念。给定n个不同的元素,排列指的是这些元素按照一定顺序的排列方式。对于数字1、2、3来说,所有可能的排列有:(1,2,3)、(1,3,2)、(2,1,3)、(2,3,1)、(3,1,2)、(3,2,1)。
字典序是一种常见的排列比较方式,类似于字典中单词的排序规则。在数字排列中,从左到右逐位比较,第一个不同的数字决定了排列的大小关系。例如(1,2,3) < (1,3,2),因为第二位2 < 3。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 上一个排列的定义与意义
上一个排列指的是在当前排列的字典序排列中,紧邻当前排列且比它小的那个排列。例如对于排列(1,3,2),它的上一个排列是(1,2,3)。
理解上一个排列的概念在实际中有多种应用:
- 密码学中的密钥生成
- 组合优化问题的求解
- 测试用例的生成
- 游戏开发中的关卡排列
3. 寻找上一个排列的算法原理
3.1 直观理解算法
寻找上一个排列可以看作是对当前排列进行最小的"降级"操作。我们需要找到排列中可以调整的位置,使得新排列尽可能接近原排列但又比它小。
这个过程与寻找下一个排列对称但方向相反。关键观察点是:
- 从右向左找到第一个满足nums[i] > nums[i+1]的位置i
- 在i右侧找到最大的nums[j]满足nums[j] < nums[i]
- 交换nums[i]和nums[j]
- 将i+1到末尾的部分逆序排列
3.2 算法步骤详解
让我们通过一个具体例子来理解算法步骤。假设当前排列是(1,3,2):
- 从右向左扫描,找到第一个下降的位置。对于(1,3,2),比较3和2,发现3>2,所以i=1(第二个元素)
- 在i右侧找到最大的比nums[i]小的数。这里只有2比3小,所以j=2
- 交换nums[i]和nums[j]:(1,2,3)
- 将i+1到末尾的部分逆序:这里i+1=2,已经是末尾,无需操作
最终得到上一个排列(1,2,3)。
3.3 边界情况处理
算法需要考虑一些特殊情况:
- 已经是第一个排列(如(1,2,3)),此时没有上一个排列
- 包含重复元素的排列
- 空排列或单元素排列
对于已经是字典序最小的排列,通常返回空数组或某种特殊标记。
