1. 题目描述
整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。
例如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的下一个排列。
2. 题目示例
2.1 示例1
输入:nums = [1,2,3]
输出:[1,3,2]
2.2 示例2
输入:nums = [3,2,1]
输出:[1,2,3]
2.3 示例3
输入:nums = [1,1,5]
输出:[1,5,1]
2.4 提示
1 <= nums.length <= 1000 <= nums[i] <= 100
3. 解题思路
3.1 算法过程
标准的 “下一个排列” 算法可以描述为:
- 从后向前查找第一个相邻升序 的元素对
(i,j),满足A[i] < A[j]。此时[j,end)必然是降序 - 在
[j,end)从后向前查找第一个满足A[i] < A[k]的k。 - 将
A[i]与A[k]交换 - 可以断定这时
[j,end)必然是降序,逆置[j,end)使其升序 - 如果在步骤1找不到符合的相邻元素对,说明当前
[begin,end)为一个降序顺序,则直接跳到步骤4
3.2 可视化
- 以求
12385764的下一个排列为例。
2. 首先从后向前查找第一个相邻升序的元素对
(i,j)。这里 i=4,j=5,对应的值为5,7
3. 然后在
[j,end)从后向前查找第一个大于A[i]的值 A[k]。这里A[i]是5,故A[k]是6
4. 将
A[i]与A[k]交换。这里交换5、6
5. 这时
[j,end)必然是降序,逆置[j,end),使其升序。这里逆置[7,5,4]
因此
12385764的下一个排列就是12386457。
4. 解题代码
4.1 go
func nextPermutation(nums []int) {
i,j,k := len(nums)-2,len(nums)-1,len(nums)-1
//find: A[i]<A[j]
for i>=0 && nums[i] >= nums[j]{
i--
j--
}
if i>=0{
//find: A[i] < A[k]
for nums[i] >= nums[k]{
k--
}
//swap:A[i],A[k]
nums[i],nums[k] = nums[k],nums[i]
}
//sort: 升序
sort.Ints(nums[j:])
}
4.2 go
func nextPermutation(nums []int) {
i,j,k := len(nums)-2,len(nums)-1,len(nums)-1
//find: A[i]<A[j]
for i>=0 && nums[i] >= nums[j]{
i--
j--
}
if i>=0{
//find: A[i] < A[k]
for nums[i] >= nums[k]{
k--
}
//swap:A[i],A[k]
nums[i],nums[k] = nums[k],nums[i]
}
//reverse: A[j:end]
//比sort.Ints快点
for l,r := j,len(nums)-1; l < r; l,r = l+1,r-1{
nums[l],nums[r] = nums[r],nums[l]
}
}