【死磕算法之1刷leetcode】——324 Wiggle Sort摆动序列2

题目描述

Given an unsorted array nums, reorder it such that nums[0] < nums[1] > nums[2] < nums[3]…
Example:
Example 1:
Input: nums = [1, 5, 1, 1, 6, 4]
Output: One possible answer is [1, 4, 1, 5, 1, 6].
Example 2:
Input: nums = [1, 3, 2, 2, 3, 1]
Output: One possible answer is [2, 3, 1, 3, 1, 2].
Note:
You may assume all input has valid answer.
Follow Up:
Can you do it in O(n) time and/or in-place with O(1) extra space?

题目解析:

这道题在wiggle sort I的基础上进行了改动(题解见【死磕算法之1刷leetcode】——376 Wiggle Sort摆动序列),数组间元素直接以> 、<号进行比较,重复元素的放置变得关键。

方法1:
数组按升序排序,完成后将数组一分为二(small half元素个数和数组的偶数索引个数大小一致)small half倒序对应放置在数组偶数索引位置上(nums[0] ,nums[ 2] ,nums[4] …),将数组的large half倒序对应放置在数组奇数索引上(nums[1],nums[3],nums[5]…)
图来自leetcode discuss 题解
我们看到在奇数索引位置的数组元素,比两侧元素大。在算法中是否有可能出现奇数索引位置的数组元素和某一侧元素相等的情况?

设L>M>S,接下来讨论数组里有重复元素是否会产生两个重复元素相邻的结果。
首先要明确,在当前算法下,在一个half 里面的重复元素是不会彼此相邻的。也就是说,来自不同half 的M才有可能造成重复元素相邻的情况

数组元素为7时,3个M是可以满足Wiggle sort条件的, 数组元素为8时,4个M是可以满足条件的,总结一下,大小为n的数组中,M的个数小于floor(n)是不会出现重复元素相邻的情况的。
在这里插入图片描述在这里插入图片描述
M是small half里面最大的(在最左边一侧),是large half里最小的(在最右边一侧)。由于是两个half倒序排列赋值,所以合并之后来自不同half 的两个M也相隔甚远。

当M 的个数大于floor(n) 时:

1.若n为偶数,结果一定会出现两个M相邻的情况。
如8个元素,SMMMMMLL,将S、L、L将M全部隔开是不可能实现的。

2.若n为奇数,只有一种情况wiggle sort是有解的:M的个数等于floor(n)+1且数组其他非M元素均为L

M的个数等于floor(n)+1,此时只能将M放置在所有的偶数索引位置,数组中其他所有元素(放在奇数索引位置)只能为L,不然会出现偶数索引位置的值大于某奇数索引位置值,不满足wiggle sort性质。

题目说明表示输入数据都是有效解的,那么用这个算法一定可以找到有效解。
python代码实现:


class Solution:
    def wiggleSort(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        nums.sort()
        half  = len(nums[::2])#避免赋值时大小对不上
        #i为索引,当i为偶数(字符当前个数为奇数),被nums的倒序smaller part替换
        #i为奇数(字符当前个数为偶数),被nums的倒序larger part替换
        nums[::2],nums[1::2] = nums[:half][::-1],nums[half:][::-1]
代码注意事项

在实现过程中,遇到了几个问题,现记录如下:
1、用切片表示数组偶数索引的数量要与划分的smaller half的个数一致。
相关代码: half = len(nums[::2]),也就是half是由len(nums[::2])决定的,即len(nums[:half]) == nums[::2]
同时nums[1::2]表示数组中奇数索引的数量

len(nums[1::2]) == len(nums[:])-len(nums[::2]) == len(nums[:])-len(nums[:half]) ==len(nums[half:])

赋值双方数组大小一致,最后一行代码可顺利执行。

2、数组排序方法:

nums.sort()#时间复杂度为O(nlog(n)),默认升序排列
nums.sort(reverse = True)#降序排列

或者

   nums = sorted(nums)#默认升序排列
   nums = sorted(nums,reverse = True)#降序排列

注意:
nums.sort()返回值为None,因此nums= nums.sort()之后nums就是NoneType类型了,不能起到排序作用。

Follow up:时间复杂度为O(n)的算法

再续

猜你喜欢

转载自blog.csdn.net/gulaixiangjuejue/article/details/84862447