Skip to content
Article
Authors
On this page
Published on

下一个排列

Article
Authors

题目

整数数组的一个 排列  就是将其所有成员以序列或线性顺序排列。

  • 例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3][1,3,2][3,1,2][2,3,1] 。

整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。

  • 例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。
  • 类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。
  • 而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。

给你一个整数数组 nums ,找出 nums 的下一个排列。

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


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 <= 100
  • 0 <= nums[i] <= 100

解题思路

  • 题目有 3 个问题需要解决。如何找到下一个排列。不存在下一个排列的时候如何生成最小的排列。如何原地修改。先解决第一个问题,如何找到下一个排列。下一个排列是找到一个大于当前排序的字典序,且变大的幅度最小。那么只能将较小的数与较大数做一次原地交换。并且较小数的下标要尽量靠右,较大数也要尽可能小。原地交换以后,还需要将较大数右边的数按照升序重新排列。这样交换以后,才能生成下一个排列。以排列 [8,9,6,10,7,2] 为例:能找到的符合条件的一对「较小数」与「较大数」的组合为 6 与 7,满足「较小数」尽量靠右,而「较大数」尽可能小。当完成交换后排列变为 [8,9,7,10,6,2],此时我们可以重排「较小数」右边的序列,序列变为 [8,9,7,2,6,10]
  • 第一步:在 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,说明当前序列已经是一个最大的排列。那么应该直接执行第三步,生成最小的排列。

代码

go
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]  
}

2024 - future