这是我参与8月更文挑战的第13天,活动详情查看:8月更文挑战
31. 下一个排列
实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列(即,组合出下一个更大的整数)。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须 原地 修改,只允许使用额外常数空间。
示例 1:
输入:nums = [1,2,3] 输出:[1,3,2] 示例 2:
输入:nums = [3,2,1] 输出:[1,2,3] 示例 3:
输入:nums = [1,1,5] 输出:[1,5,1] 示例 4:
输入:nums = [1] 输出:[1]
解题思路
“下一个排列”的定义是:给定数字序列的字典序中下一个更大的排列。如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
我们可以将该问题形式化地描述为:要想获取下一个排列,我们的目标就是找到下一个刚好大于当前排列组成的字符串。 我们需要从数组尾部开始遍历,找到第一个像下面这样nums[i] < nums[i+1]数对。而数组前面部分我们不需要改变,像4123的下一个排列是4132,他们数组的前缀都是相同的。
因为这样递减的数对,我们可以保证数组后部分必然有大于当前转折点nums[i]的元素nums[k],将这两个元素交换位置,就能使得当前排列的第i位增大,而后面第i+1位以后的数字是单调递减的(属于最大的排列),所以我们必须将其倒序,变成递增的
/\
/ \
\
\
代码
func nextPermutation(nums []int) {
i := len(nums) - 2
for i >= 0 && nums[i] >= nums[i+1] {
i--
}
if i >= 0 {
k := len(nums) - 1
for nums[k] <= nums[i] {
k--
}
nums[k], nums[i] = nums[i], nums[k]
}
// reverse A[j:end]
for l, j := i+1, len(nums)-1; l < j; l, j = l+1, j-1 {
nums[l], nums[j] = nums[j], nums[l]
}
}