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 and use only constant 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
题意:
给一个数列,从左到右按照高位到低位当作一个整数(num),返回一个由相同数字不同组合比 num 的数。要求返回的结果是大于num且与num最为相近的数,如果不存在(即 数列的数是降序排列的),那么将数列按升序排列后输出。
分析:
使用所给列表的元素,从左到右按照有高到低位的顺序组成为一个整数(假设为num),需要求得比num大的新组合newNum,同时还要求newNum - num的值最小,所以 只有当尽可能确保两数的高位部分相等时,两数间的差才会较小。实现思路如下:
- 首先,使用imin标记为最后一位元素的下标。
- 从倒数第二位元素开始向前遍历,查找最右边的相邻两个元素且为左小右大的位置,如果找到把imin替换为较小元素的下标,并且终止循环(这里是因为,当发现最最右端出现高位的数字比低位的数字小时,此时可以保证最多的高位数对应相等,因为 可以把第一个符合条件的元素位置当作需要替换为较大值的位置)。
- 如果第二步的循环执行完毕,且imin仍然为最后一位元素的下标时,即可将数列按升序排列,并返回结果。因为只有所有的相邻元素均为左边大于右边时,此时可以说明原列表元素是降序排列的,因此不存在本题所要求的解。
- 找到最右边需要替换的位置之后。接下来需要找使用哪个数替换产生的数值会比原来的大,且两个数相距较近。因为高位元素保持不变了,所以接下来只需要在上面求得的imin位置后面查到到一个大于它但与它又是最仅的元素位置,进行替换即可。(这里取imin右边最小的大于imin位置的元素,是因为 如果仅是大于imin位置的元素,那么可能会产生不是最接近原数值的结果)。
- 相应位置的元素替换之后,此时数列中[0,imin]之间组成的数,已经比原来的数值要大了,因为imin相对后面的数为最高位,所以当求与原数值最接近的结果时,现在只需要保证imin后的元素所构成的数值最下即可,又因 升序排列所构成的数值一定最小,因此这里直接升序排列imin后面的元素即可。
- 返回结果。实现如下
Code & C++
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int imin = nums.size()-1;
for(int i=nums.size()-2; i>=0; --i){
if(nums[i]<nums[i+1]){
imin = i;
break;
}
}
if(imin == nums.size()-1){
return sort(nums.begin(), nums.end());
}
int maxnum = numeric_limits<int>::max(), idx=-1;
for(int i=nums.size()-1;i>imin;--i){
if(nums[i] > nums[imin] && nums[i]<maxnum ){
maxnum = nums[i];
idx = i;
}
}
swap(nums[imin], nums[idx]);
sort(nums.begin()+imin+1,nums.end());
}
};
Result:
Runtime: 12 ms, faster than 100.00% of C++ online submissions for Next Permutation.
Memory Usage: 10.2 MB, less than 24.63% of C++ online submissions for Next Permutation.
Code & Python
class Solution:
def nextPermutation(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
i = len(nums)-1
while i>0 and nums[i] <= nums[i-1]:
i-=1
if i == 0:
nums.sort()
else:
i , j , maxnum , idx=i-1, len(nums)-1, 1<<31, -1
while i<j:
if nums[j] > nums[i] and nums[j] < maxnum:
maxnum, idx = nums[j], j
j-=1
nums[i], nums[idx] = nums[idx], nums[i]
nums[i+1:] = sorted(nums[i+1:])
Result
Runtime: 48 ms, faster than 65.63% of Python3 online submissions for Next Permutation.
Memory Usage: 13.3 MB, less than 5.24% of Python3 online submissions for Next Permutation.