website/content/ChapterFour/0001~0099/0031.Next-Permutation.md
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.
If such an arrangement is not possible, it must rearrange it as the lowest possible order (i.e., sorted in ascending order).
The replacement must be in place and use only constant extra memory.
Example 1:
Input: nums = [1,2,3]
Output: [1,3,2]
Example 2:
Input: nums = [3,2,1]
Output: [1,2,3]
Example 3:
Input: nums = [1,1,5]
Output: [1,5,1]
Example 4:
Input: nums = [1]
Output: [1]
Constraints:
1 <= nums.length <= 1000 <= nums[i] <= 100实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。必须 原地 修改,只允许使用额外常数空间。
nums[i] 中找到 i 使得 nums[i] < nums[i+1],此时较小数为 nums[i],并且 [i+1, n) 一定为下降区间。第二步:如果找到了这样的 i ,则在下降区间 [i+1, n) 中从后往前找到第一个 j ,使得 nums[i] < nums[j] ,此时较大数为 nums[j]。第三步,交换 nums[i] 和 nums[j],此时区间 [i+1, n) 一定为降序区间。最后原地交换 [i+1, n) 区间内的元素,使其变为升序,无需对该区间进行排序。i,说明当前序列已经是一个最大的排列。那么应该直接执行第三步,生成最小的排列。package leetcode
// 解法一
func nextPermutation(nums []int) {
i, j := 0, 0
for i = len(nums) - 2; i >= 0; i-- {
if nums[i] < nums[i+1] {
break
}
}
if i >= 0 {
for j = len(nums) - 1; j > i; j-- {
if nums[j] > nums[i] {
break
}
}
swap(&nums, i, j)
}
reverse(&nums, i+1, len(nums)-1)
}
func reverse(nums *[]int, i, j int) {
for i < j {
swap(nums, i, j)
i++
j--
}
}
func swap(nums *[]int, i, j int) {
(*nums)[i], (*nums)[j] = (*nums)[j], (*nums)[i]
}
// 解法二
// [2,(3),6,5,4,1] -> 2,(4),6,5,(3),1 -> 2,4, 1,3,5,6
func nextPermutation1(nums []int) {
var n = len(nums)
var pIdx = checkPermutationPossibility(nums)
if pIdx == -1 {
reverse(&nums, 0, n-1)
return
}
var rp = len(nums) - 1
// start from right most to leftward,find the first number which is larger than PIVOT
for rp > 0 {
if nums[rp] > nums[pIdx] {
swap(&nums, pIdx, rp)
break
} else {
rp--
}
}
// Finally, Reverse all elements which are right from pivot
reverse(&nums, pIdx+1, n-1)
}
// checkPermutationPossibility returns 1st occurrence Index where
// value is in decreasing order(from right to left)
// returns -1 if not found(it's already in its last permutation)
func checkPermutationPossibility(nums []int) (idx int) {
// search right to left for 1st number(from right) that is not in increasing order
var rp = len(nums) - 1
for rp > 0 {
if nums[rp-1] < nums[rp] {
idx = rp - 1
return idx
}
rp--
}
return -1
}