题目难度: 中等
今天继续更新程序员面试金典系列, 大家在公众号 算法精选 里回复 面试金典 就能看到该系列当前连载的所有文章了, 记得关注哦~
题目描述
在一个整数数组中,“峰”是大于或等于相邻整数的元素,相应地,“谷”是小于或等于相邻整数的元素。例如,在数组{5, 8, 4, 2, 3, 4, 6}中,{8, 6}是峰, {5, 2}是谷。现在给定一个整数数组,将该数组按峰与谷的交替顺序排序。
示例:
- 输入: [5, 3, 1, 2, 3]
- 输出: [5, 1, 3, 2, 3]
提示:
- nums.length <= 10000
题目思考
- 如何利用已经排好序的部分?
解决方案
思路
- 分析题目, 不难发现偶数下标需要是峰, 而奇数下标需要是谷
- 这里我们可以使用贪心的做法, 从前向后遍历整个数组, 判断当前遍历的数字是否满足要求, 不满足时将其与后面满足要求的数字进行交换, 从而不影响已经排序好的部分
- 既然前面的数字已经排好序了, 这里我们只需要比较当前数字和后一位数字即可, 如果当前数字不满足要求, 那么后一位数字一定满足要求, 将他们交换然后继续向后遍历, 最终即可得到整体排序的数组
- 具体证明如下:
- 假如当前下标 i 需要是峰(偶数下标), 且前面的 0~i-1 都满足要求, 那么 i-1 是谷,
nums[i]>=nums[i-1]
- 此时如果
nums[i]>=nums[i+1]
, 则 i 是满足要求的峰 - 而如果
nums[i]<nums[i+1]
, 那么nums[i+1]>nums[i]>=nums[i-1]
, 即 nums[i+1]是满足要求的峰, 交换 nums[i]与 nums[i+1]即可
- 此时如果
- 假如当前下标 i 需要是谷(奇数下标), 且前面的 0~i-1 都满足要求, 那么 i-1 是峰,
nums[i]<=nums[i-1]
- 此时如果
nums[i]<=nums[i+1]
, 则 i 是满足要求的谷 - 而如果
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]
大家可以在下面这些地方找到我~😊
我的公众号: 算法精选, 欢迎大家扫码关注~😊