问题描述
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
思路分析
这题是Medium难度,不算难。
以[1,2,4,3,1]数组为例,解题步骤为:
- 从后向前找到数组的第一个上升位置i=2,i-1位置处的数字为待对调的数字(记为key);
- 从key后寻找第一个不比key大的数字位置j=4,那么j-1位置处为最后一个比key大的数字;
- 对调i-1、j-1位置处的数字,得到[1,3,4,2,1];
- 将[i, len(nums)-1]子串反置,得到结果[1,3,1,2,4];
- 若找不到上升位置,说明数组完全降序,因此将其反置,得到升序数组。
AC代码
#encoding=utf-8
class Solution(object):
def nextPermutation(self, nums):
"""
:type nums: List[int]
:rtype: void 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:
j = i
#二分查找比上升处数值大的最后一个数
j = self.midSearch(nums[i-1], nums, i, len(nums) - 1)
tmp = nums[i-1] #对调这两个数
nums[i-1] = nums[j-1]
nums[j-1] = tmp
#对调后上升数后面的数列由降序改为升序
if i < len(nums) - 1:
p = i
q = len(nums) - 1
while p < q:
tmp = nums[p]
nums[p] = nums[q]
nums[q] = tmp
p += 1
q -= 1
return
#若原数组严格降序,则改为升序(不用排序算法,直接反置数组)
p = 0
q = len(nums) - 1
while p < q:
tmp = nums[p]
nums[p] = nums[q]
nums[q] = tmp
p += 1
q -= 1
def midSearch(self, key, nums, p, q):
if p == q:
if nums[p] > key:
return p + 1
else:
return p
mid = (p + q) / 2
if nums[mid] > key:
return self.midSearch(key, nums, mid+1, q)
else:
return self.midSearch(key, nums, p, mid)
Runtime: 60 ms, which beats 77.71% of python submissions.