标签:vpd instead odi range 技术 and bash 观察 是什么
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
思路:迭代
首先先理解题意,题目中要求【将给定数字序列重新排列成字典序中下一个更大的排列。如果不存在,则将数字重新排列称最小的排列(即升序排列)】
在这里,可能直接从文字上面来看,不太不能够理解是什么意思,那么结合例子来看,先看
1,2,3 → 1,3,2
1,1,5 → 1,5,1
在这里,你可以理解为,要将数字 123 变为下一个更大的数字,132。115 也同理。
而下面这个例子就是表示不存在更大的排列:
3,2,1 → 1,2,3
321 已经是最大的了,那么就将其排列为最小的排列(升序排列),得到结果 123。
其实从上面的例子中,多多少少也能够看出来,在这里其实是从后面开始找,当找到相邻升序的两个数字,在这里将它们进行交换,这样就能够得到更大的排列。
其实这里还有一部分的内容,在题目中是比较难看出来的,题目中【下一个】这个概念,其实要找到的是变化前后的排列,增加的幅度尽可能小。比如,下面的例子:
1,2,3,4,5 → 1,2,3,5,4
1,2,3,5,4 → 1,2,4,3,5
第一个示例,根据上面观察所得,即是将 4 和 5 进行替换,得到更大的排列,12354。
后面的示例中 12354,得到排列的结果 12435。在这里,交换的是 3 和 4,这里其实交换的数字是尽可能小的大数和前面的小数,所以并不是 3 和 5 进行交换,而交换后的所有数还需要重置升序。所得出的结果是 12435,而不是 12453。
这就是关于题意的简单分析,下面看如何实现算法:
具体的代码实现如下。
class Solution:
def nextPermutation(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
if len(nums) < 2:
return
n = len(nums)
# 从数组右往前进行遍历,查找相邻升序元素
i = n - 2
j = n - 1
while i > 0 and nums[i] >= nums[j]:
i -= 1
j -= 1
# 这里有一种情况,就是循环结束后,i 为 0 且索引 0 位置的数是最大的情况
# 那这里就表示排列就是最大的排列,将其逆转升序
if i == 0 and nums[i]==max(nums):
nums.reverse()
else:
# 当找到相邻的升序元素时
# 再次从后往前找到一个比 nums[i] 大但相比其他元素尽可能小的数
k = n - 1
while nums[i] >= nums[k]:
k -= 1
# 交换两个元素
nums[i], nums[k] = nums[k], nums[i]
# 现在 j 到后面的元素是降序的,这里要将其升序
length = n - j + 1
for x in range(length // 2):
nums[j+x], nums[n-1-x] = nums[n-1-x], nums[j+x]
以上就是关于《31. 下一个排列》问题的分析及具体实现算法的主要内容。
欢迎关注微信公众号《书所集录》
标签:vpd instead odi range 技术 and bash 观察 是什么
原文地址:https://www.cnblogs.com/yiluolion/p/12901909.html