31. 下一个排列

题目描述

实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。

如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。

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

以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,31,3,2
3,2,11,2,3
1,1,51,5,1**


思路

从不存在入手,如果不存在下一个更大排列,这个排列一定是一个非严格降序(存在等号)排列。

  • 翻转序列,即为题中要求的下一个更大序列。

那么如果存在下一个更大的排列,在原始排列中一定存在一小段严格升序的排列

  • 从末尾开始遍历排列,找到第一个升序位置,即nums[i] > nums[i-1]
  • [i+1,n)的区间上找到比nums[i]大的元素位置jnums[i]nums[j]进行交换,这样保证前边是不变的,后边的序列会变大。
  • [i+1,n)中的序列是降序的,将其进行翻转,使得后边的序列最小,总体的排列即下一个最大的排列。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int n = nums.size(), i = n - 2, j = n - 1;
if(n==0 || n==1) return;
while(i >= 0 && nums[i] >= nums[i+1]) {
--i;
}
if(i != -1) {
while(j > i) {
if(nums[j] > nums[i]) break;
--j;
}
swap(nums[i], nums[j]);
reverse(nums.begin() + i + 1,nums.end() );
} else {
reverse(nums.begin(), nums.end());
}

}
};

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!