必须 原地 修改,只允许使用额外常数空间
下一个排列
- 我们希望下一个数 比当前数大,这样才满足 “下一个排列” 的定义。因此只需要 将后面的「大数」与前面的「小数」交换,就能得到一个更大的数。比如
123456
,将5
和6
交换就能得到一个更大的数123465
- 我们还希望下一个数 增加的幅度尽可能的小,这样才满足“下一个排列与当前排列紧邻“的要求。为了满足这个要求,我们需要:
- 在 尽可能靠右的低位 进行交换,需要 从后向前 查找
- 将一个 尽可能小的「大数」 与前面的「小数」交换。比如
123465
,下一个排列应该把5
和4
交换而不是把6
和4
交换 - 将「大数」换到前面后,需要将「大数」后面的所有数 重置为升序,升序排列就是最小的排列。以
123465
为例:首先按照上一步,交换5
和4
,得到123564
;然后需要将5
之后的数重置为升序,得到123546
。显然123546
比123564
更小,123546
就是123465
的下一个排列
func nextPermutation(nums []int) { // 1 3 2
n := len(nums)
// 从右往左,第一个小于右侧数字的位置
i := n - 2
for i >= 0 && nums[i] >= nums[i + 1] {
i--
}
// 从右往左,第一个小于 nums[i] 的位置
j := n - 1
if i >= 0 { // 不是最后一个排列
for nums[i] >= nums[j] {
j--
}
nums[i], nums[j] = nums[j], nums[i]
}
for i, j = i + 1, n - 1; i < j; i, j = i + 1, j - 1 {
nums[i], nums[j] = nums[j], nums[i]
}
}