必须 原地 修改,只允许使用额外常数空间

下一个排列

  • 我们希望下一个数 比当前数大,这样才满足 “下一个排列” 的定义。因此只需要 将后面的「大数」与前面的「小数」交换,就能得到一个更大的数。比如 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]
	}
}