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.
题目的意思就是给出一串数字,求出它的全排列方式中与它本身最接近的一个比它大的数字排列。如果已经是最大的排列方式了,则返回全排列中最小的那种排列方式。例如:
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
思路一:暴力求解
先求出全排列的所有情况,然后找出比nums大的下一个排列。但是这种情况时间超出,不能ac,仅供参考。
Python 代码实现
class Solution:
def getSortedPermutation(self, nums: List[int]) -> List:
ansSet = {}
if len(nums) == 1:
return [nums]
lastArray = self.getSortedPermutation(nums[0:len(nums)-1])
for last in lastArray:
l = len(last)
for i in range(l+1):
tmpLast = last[:]
tmpLast.insert(i,nums[-1])
lastKey = self.toString(tmpLast)
ansSet[lastKey]=tmpLast
ans = [List for i in range(len(ansSet))]
index = 0
for s,value in ansSet.items():
ans[index] = value
index+=1
return ans
def toString(self,nums: List[int]) -> str:
return "".join(str(x) for x in nums)
def nextPermutation(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
allAns = self.getSortedPermutation(nums)
allAns.sort()
res = 0
for i in range(len(allAns)):
if self.toString(allAns[i]) == self.toString(nums):
res = i
if res == len(allAns) - 1:
res = 0
else:
res+=1
for i in range(len(nums)):
nums[i] = allAns[res][i]
思路二
由于要找的是比当前数大得最接近的那个数,所以假设后面的某一段是降序,只要在这个降序部分找到一个数字大于这段的前面那个数字,然后交换一下这两个数,在将降序部分翻转,即可得到最终结果。
下面这个动图很直观:
就是从后向前查找,知道找出相邻两个是降序的数字,比如这里的(7,4),然后取较小的那个。然后再在它的后面的比它(4)大的数中找到最小的那个(也就是刚好比4大的一个数),这里就是5,然后交换这两个树的位置,也就是4和5交换,最后对5后面那部分进行升序排列。这样就得到了结果。
import copy
class Solution:
def swap(self,nums: List[int], i, j):
temp = nums[i]
nums[i] = nums[j]
nums[j] = temp
def reverse(self,nums: List[int], start):
i = start
j = len(nums) - 1
while (i < j) :
self.swap(nums, i, j)
i+=1;
j-=1;
def nextPermutation(self, nums: List[int]) -> None:
i = len(nums) - 2
# 先找到降序的那个数x
while (i >= 0 and nums[i + 1] <= nums[i]):
i-=1
# 由于上面的代码已经保证了x后面都是降序。
# 所以只要从最后一位向前遍历,找到第一个比x小的数即可。
if (i >= 0) :
j = len(nums) - 1
while (j >= 0 and nums[j] <= nums[i]):
j-=1
self.swap(nums, i, j)
# 升序排列后部分
self.reverse(nums, i + 1)
THE END.