这两天屁事儿特别多,就一直没有更新,心里其实慌慌的,一是感觉自己太懒了,二是觉得有些对不起大家,所以今天闲下来了赶紧更新一波!
31-下一个排列
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。1,2,3
→ 1,3,2
3,2,1
→ 1,2,3
1,1,5
→ 1,5,1
说到这一题,我踩得坑那着实是不少,之前没有把题目意思仔细研读,就匆匆动笔了,导致后面bug十多次,而气的是自己一直以为自己没有做错。
我第一次的想法是这样的:采用python中itertools.permutations()排列函数首先求得给定序列当中的数不同的排列情况,然后依次遍历,只要发现有比原序列大,立即返回该系列。我写的代码很简单,当时觉得自己太聪明了,只有天才如自己才能想到这么简单的办法,谁知道bug十多次,当时已经崩溃了。
代码如下:
from itertools import permutations
class Solution:
def nextPermutation(self, nums):
"""
:type nums: List[int]
:rtype: void Do not return anything, modify nums in-place instead.
"""
if len(nums) == 0 or len(nums) == 1:
return
# 求得给定序列当中的数不同的排列情况
nums_permutation = list(permutations(nums))
# 依次遍历nums_permutation求得第一个比nums大的序列返回
for index in nums_permutation:
index = list(index)
if index > nums:
nums[:] = index
print("nums", nums)
return
nums.sort()
print(nums)
if __name__ == "__main__":
nums = [1, 2, 3]
Solution().nextPermutation(nums)
大家感兴趣的也可以run run试试,很有意思的,相信我!
当时气得没办法,找了网上的大神,看到他们的解法才知道我的问题出在哪儿,核心点就是我没有考虑到将给定数字序列重新排列成字典序中下一个更大的排列。这个顺序才是最关键的,而我之前并没有考虑,问题找到了,那做起来就很快了。
思路:
- 首先找到nums数组中从右往左第一个左边值比右边值小的下标值,如果没找到(即该序列为规则的逆序序列)
- 再将该下标值对应的数与后面最后一个比它大的数交换
- 交换完之后,将1中找到的下标值后面的所有数升序排列
代码如下:
class Solution:
def nextPermutation(self, nums):
"""
:type nums: List[int]
:rtype: void Do not return anything, modify nums in-place instead.
"""
# 首先找到nums数组中从右往左第一个左边值比右边值小的下标值
if len(nums) == 0 or len(nums) == 1:
return
index = len(nums) - 2
while index >= 0 and nums[index] >= nums[index+1]:
index -= 1
if index >= 0:
self.swap(nums, index)
# 然后将index后面的值用sort()方法从小到大排列
nums_copy = []
nums_copy.extend(nums[index+1:])
nums_copy.sort()
nums[index+1:] = nums_copy
print("nums", nums)
return
nums.sort()
print("nums", nums)
# 将找到的index下标值与相邻最大的值交换
def swap(self, nums, index):
for next_index in range(len(nums)-1, index, -1):
if nums[next_index] > nums[index]:
temp = nums[index]
nums[index] = nums[next_index]
nums[next_index] = temp
return
执行效率在70%以上。