31. 下一个排列
题目描述
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
要求:必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
分析:首先明白,下一个排列一定是比当前的数字大的,
如1 2 3 4 6 5 7 --> 1 2 3 4 6 7 5 ,一个数想要变大,而且是最小程度的变大,那么就会想到,把个位数变大,但是题目要求的中每个数位的数字和个数是固定的,所以只能通过交换位置把低位上的较大的数和高位的较小的数交换,把数变大,那么从后往前,把较大的数换到前面去,这个数就会变大,想要最接近的变大,硬核:根据维基百科下一个排列定义:
翻译后步骤如下:
1.先找出最大的索引 k 满足 nums[k] < nums[k+1],如果不存在,就翻转整个数组;
2.再找出另一个最大索引 l 满足 nums[l] > nums[k];
3.交换 nums[l] 和 nums[k];
4.最后翻转 nums[k+1:]。
参考leetcode 的powcai 大佬的方法
def nextPermutation(nums):
"""
:type nums: List[int]
:rtype: None Do not return anything, modify nums in-place instead.
"""
def nums_reverse(start,end):
while start < end:
nums[start],nums[end] = nums[end],nums[start]
start += 1
end -= 1
ans = []
n = len(nums)
if n <= 1 :
return nums
firstindex = -1
for i in range(n-2,-1,-1):
if nums[i] < nums[i+1]:
firstindex = i
break
print("firstindex",firstindex)
if firstindex == -1 :
nums_reverse(0,n-1)
print(nums)
return
secondindex = -1
for j in range(n-1,firstindex,-1):
if nums[j] > nums[firstindex]:
secondindex = j
break
print(firstindex,secondindex)
nums[firstindex],nums[secondindex] = nums[secondindex],nums[firstindex]
nums_reverse(firstindex + 1 ,n-1)
print(nums)
nums = [3,2,1]
# 4 2 0 2 3 2 0 ==》 4 2 0 3 0 2 2
nextPermutation(nums)
题目总结:数组的原地更改指的是数组的内存地址不变,不能直接申请一块内存直接创建一个新数组,哪怕是数组名字一样,内存地址也是不同的。