程序员面试金典 - 面试题 10.11. 峰与谷

题目难度: 中等

原题链接

今天继续更新程序员面试金典系列, 大家在公众号 算法精选 里回复 面试金典 就能看到该系列当前连载的所有文章了, 记得关注哦~

题目描述

在一个整数数组中,“峰”是大于或等于相邻整数的元素,相应地,“谷”是小于或等于相邻整数的元素。例如,在数组{5, 8, 4, 2, 3, 4, 6}中,{8, 6}是峰, {5, 2}是谷。现在给定一个整数数组,将该数组按峰与谷的交替顺序排序。

示例:

  • 输入: [5, 3, 1, 2, 3]
  • 输出: [5, 1, 3, 2, 3]

提示:

  • nums.length <= 10000

题目思考

  1. 如何利用已经排好序的部分?

解决方案

思路
  • 分析题目, 不难发现偶数下标需要是峰, 而奇数下标需要是谷
  • 这里我们可以使用贪心的做法, 从前向后遍历整个数组, 判断当前遍历的数字是否满足要求, 不满足时将其与后面满足要求的数字进行交换, 从而不影响已经排序好的部分
  • 既然前面的数字已经排好序了, 这里我们只需要比较当前数字和后一位数字即可, 如果当前数字不满足要求, 那么后一位数字一定满足要求, 将他们交换然后继续向后遍历, 最终即可得到整体排序的数组
  • 具体证明如下:
  1. 假如当前下标 i 需要是峰(偶数下标), 且前面的 0~i-1 都满足要求, 那么 i-1 是谷, nums[i]>=nums[i-1]
    1. 此时如果 nums[i]>=nums[i+1], 则 i 是满足要求的峰
    2. 而如果 nums[i]<nums[i+1], 那么 nums[i+1]>nums[i]>=nums[i-1], 即 nums[i+1]是满足要求的峰, 交换 nums[i]与 nums[i+1]即可
  2. 假如当前下标 i 需要是谷(奇数下标), 且前面的 0~i-1 都满足要求, 那么 i-1 是峰, nums[i]<=nums[i-1]
    1. 此时如果 nums[i]<=nums[i+1], 则 i 是满足要求的谷
    2. 而如果 nums[i]>nums[i+1], 那么 nums[i+1]<nums[i]<=nums[i-1], 即 nums[i+1]是满足要求的谷, 交换 nums[i]与 nums[i+1]即可
  • 下面的代码就对应了上面的整个过程, 并且有详细的注释, 方便大家理解
复杂度
  • 时间复杂度 O(N): 只需要遍历整个数组一遍
  • 空间复杂度 O(1): 只使用了几个常数空间的变量
代码
class Solution:
    def wiggleSort(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        # 贪心+偶峰奇谷+不满足时交换
        # 一次遍历, 若当前下标数字不满足要求, 则与后一位数字交换继续向后遍历, 不会影响之前已经排序好的峰谷
        for i in range(len(nums) - 1):
            # 偶数下标时需要是峰, peek是True
            peek = i & 1 == 0
            if peek and nums[i] < nums[i + 1] or not peek and nums[i] > nums[i + 1]:
                # 如果当前下标不满足要求, 则与下一个数字交换即可
                nums[i], nums[i + 1] = nums[i + 1], nums[i]

大家可以在下面这些地方找到我~😊

我的 GitHub

我的 Leetcode

我的 CSDN

我的知乎专栏

我的头条号

我的牛客网博客

我的公众号: 算法精选, 欢迎大家扫码关注~😊

算法精选 - 微信扫一扫关注我

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值