031_Next Permutation
Next Permutation
Difficulty Medium
tags two-pointers
permutation
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.
If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).
The replacement must be in-place, do not allocate extra memory.
Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3
→ 1,3,2
3,2,1
→ 1,2,3
1,1,5
→ 1,5,1
思路
这是一个不难从观察中得到方法的算法, 而且即使在数组中有相同的元素的情况下也能通过细微的改动在~N的时间复杂度下实现此算法。
以 [1, 4, 3, 2] 为例, 其下一个排列为 [2, 1, 3, 4]
通过观察可以发现,将上一个排列转换到下一个排列的过程中, 我们的思考方式是这样的:
排列尾部的[4,3,2]已经达到了2,3,4这三个元素形成的排列中最大的一个, 所以我们必须考虑换掉数组头上的1来实现下一个排列。
因此,自然我们需要从2,3,4中挑选一个最接近1的:2 来放在排列头部。 然后,因为2是新的队首, 后面的排列取顺序递增排列即可。
原来的尾部排列已经逆向有序, 我们将要替换的两个最接近的元素交换后, 并不影响其有序性。所以,将尾部数组再逆序一下就是顺序数组了。
也即我们所求的排列。
solution 1
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int n = nums.size();
int p = n-2;
while (p>=0 && nums[p]>=nums[p+1]){
p--;
}
if (p>=0) {
int min_diff = INT_MAX, ptr = p+1, pos;
while (ptr<n) {
if (nums[ptr]>nums[p] && nums[ptr]-nums[p]<=min_diff) {
min_diff = nums[ptr]-nums[p];
pos = ptr;
}
ptr++;
}
swap(nums[p], nums[pos]);
}
reverse(nums.begin()+p+1, nums.end());
}
};