324. 摆动排序 II(双指针+桶排序)

127 阅读3分钟

image.jpeg

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第25天,点击查看活动详情

测试岗位也越来卷了,除了基本的功能测试外,还要有编程基础、脚本经验才脱颖而出。

怎么才能提高我们的编程能力呢,刷LeetCode是最佳的途径之一,话不多数,刷题走起~

一、题目描述:

  • 题目内容

    image.png

  • 题目示例

    image.png

  • 题目提示

    • 1 <= nums.length <= 5 * 104
    • 0 <= nums[i] <= 5000
    • 题目数据保证,对于给定的输入 nums ,总能产生满足题目要求的结果

二、思路分析:

我们今天拿到本题是 leetcode 难度为中等题 324. 摆动排序 II。题目要求对一组数组元素按照奇数位元素大于偶数位元素。需要注意的题目细节点有如下几点:

  • 输入的nums数组进行排序后能得到满足要求的结果
  • 输入的nums数组中元素有重复的元素,但其数量一定小于(n+1)/2

根据题目内容,我们可以使用双指针排序方法来进行排序,思路如下:

  • 方法一:双指针排序

    • nums中元素排序后要达到奇数索引位置的值大于偶数索引位置的值
    • 首先对nums数组进行升序排序并赋值给tmp变量
    • 同时定义两个指针left和right,left指针向tmp的中部位置(len(nums)-1)/2,right指针指向tmp末尾len(nums)-1
    • for循环遍历len(nums),left和right指针从右向左移动
    • 当i为偶数时,则nums[i]赋值为tmp[left],left向左移动一步
    • 当i为奇数时,则nums[i]赋值为tmp[right],right向左移动一步
    class Solution(object):
        def wiggleSort(self, nums):
            """
            :type nums: List[int]
            :rtype: None Do not return anything, modify nums in-place instead.
            """
            n = len(nums)
            tmp = sorted(nums)
            left = (n-1)/2
            right = n-1
            for i in range(n):
                if i % 2 == 0:
                    nums[i] = tmp[left]
                    left -=1
                else:
                    nums[i] = tmp[right]
                    right -=1
    
  • 方法二:桶排序

    • 将nums[i]元素为索引位置放入stuck数组中,stuck[nums[i]]为该元素出现的次数
    • stuck为定义的最大长为5001,元素初始化都0的数组,开始指针j从5000索引位置开始
    • 第一个for循环对nums奇数位的索引进行插入数字,将最大数字依次填入nums奇数位
    • 第二个for循环对nums偶数位的索引进行插入数字,将较小的数字依次填入nums偶数位
    class Solution(object):
        def wiggleSort(self, nums):
            """
            :type nums: List[int]
            :rtype: None Do not return anything, modify nums in-place instead.
            """
    
            stuck = [0]*5001
            j = 5000
    
            for num in nums:
                stuck[num] +=1
    
            for i in range(1,len(nums),2):
                while stuck[j]==0:
                    j -=1
                nums[i] = j
                stuck[j] -=1
    
            for i in range(0,len(nums),2):
                while stuck[j]==0:
                    j -=1
                nums[i] = j
                stuck[j] -=1
    
  • 方法三:切片

    • nums进行预处理进行升序排列
    • nums偶数索引位置元素切片取0~(len(nums)+1)//2,并倒序排序
    • nums奇数索引位置元素切片取(len(nums)+1)//2~len(nums),并倒序排序
    class Solution(object):
        def wiggleSort(self, nums):
            nums.sort()
            nums[::2], nums[1::2] = nums[:(len(nums) + 1) // 2][::-1], nums[(len(nums) + 1)//2:][::-1]
    

三、总结:

本题是一道关于数组排序,本题中需要明确的是奇数位的数要大于偶数位的数,且nums排序后是满足条件的,因此对nums进行升序排序后,则存在最多(n+1)/2的次相同的元素,因此从left指针初始位置指向(n-1)/2位置开始倒序遍历。双指针法AC提交记录如下:

image.png

  • 时间复杂度:O(nlogn),n为nums数组长度,排序需要logn时间
  • 空间复杂度:O(n),需要对原数组进行拷贝,n为nums数组空间

以上是本期内容,欢迎大佬们点赞评论,下期见~~~