[排序] 324. 摆动排序 II

92 阅读1分钟

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

每日刷题 2022.06.30

题目

  • 给你一个整数数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]... 的顺序。
  • 你可以假设所有输入数组都可以得到满足题目要求的结果。

示例

  • 示例1
输入:nums = [1,5,1,1,6,4]
输出:[1,6,1,5,1,4]
解释:[1,4,1,5,1,6] 同样是符合题目要求的结果,可以被判题程序接受。
  • 示例2
输入: nums = [1,3,2,2,3,1]
输出: [2,3,1,3,1,2]

提示

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

解题思路

  • 分析题目含义:对于中间的数来说,两边一定是小于的,有点类似于山丘的样子。
  • 那么问题来了:怎么才能保证中间的数一定是大于两边的数呢?可以通过排序,就较大的数安排在两个数之间。
  • 实例演示:
    • 初始数组如下:[1,3,2,2,3,1]===原始数组
    • 降序排序:[3,3,2,2,1,1]===排序数组
    • 将原始数组的奇数位直接依次用排序数组填满 将原始数组的偶数位直接依次用排序数组填满;实际上是实现了:依次把排序好的大的数放在奇数位,依次把排序好的小的数放在偶数位 小 <大 > 小<大>小<大>小
  • 注意⚠️:这里用降序排序可以避免一个bug,遇到重复的数字,举个例子:1223 排序后 1<2>2<3显然不对。如果是降序排序 3221:2<3>1<2

AC代码

var wiggleSort = function(nums) {
    const arr = nums.slice();
    arr.sort((a, b) => a - b);
    const n = nums.length;
    const x = Math.floor((n + 1) / 2);
    for (let i = 0, j = x - 1, k = n - 1; i < n; i += 2, j--, k--) {
        nums[i] = arr[j];
        if (i + 1 < n) {
            nums[i + 1] = arr[k];
        }
    }
};