持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情
一 描述
324. 摆动排序 II - 力扣(LeetCode)
给你一个整数数组 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 * 104
- 0 <= nums[i] <= 5000
- 题目数据保证,对于给定的输入 nums ,总能产生满足题目要求的结果
进阶:你能用 O(n) 时间复杂度和 / 或原地 O(1) 额外空间来实现吗?
二 分析
排序。
观察题目,可知,可以对数组排序,然后等分为左右子数组,保证较小值的子数组的长度不小于另一子数组长度。
然后两个数组穿插排序,即归并排序的最后一步。
进阶
需要O(n)的时间复杂度或者O(1)的空间复杂度
因为排序方法的时间复杂度是nlogn,所以为了n的时间复杂度,不能全部排序。
观察可知,不需要全部排序,我们只需要将数组分为左右子数组,保证左数组的值全部小于等于右数组即可。
所以用快速选择算法,得到中位数,将数组分为左、中、右三个子数组,然后归并。
三 答案
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
const getMid = (left, right, nums) => {
const l = nums.length;
let mid = nums[~~(l / 2)];
const leftL = [],
rightL = [];
let v = 0;
for (const n of nums) {
if (n > mid) {
rightL.push(n);
} else if (n < mid) {
leftL.push(n);
} else {
v++;
}
}
if (Math.abs(left + leftL.length - right - rightL.length) <= v) return mid;
if (left + leftL.length > right + rightL.length) {
return getMid(left, rightL.length + right + v, leftL);
} else {
return getMid(left + leftL.length + v, right, rightL);
}
};
var wiggleSort = function (nums) {
const l = nums.length;
const mid = getMid(0, 0, nums.slice());
const left = [],
right = [];
let v = 0;
for (const n of nums) {
if (n > mid) {
right.push(n);
} else if (n < mid) {
left.push(n);
} else {
v++;
}
}
const c = left.length - right.length;
if (c == 0) {
left.splice(0, 0, ...new Array(Math.ceil(v / 2)).fill(mid));
right.push(...new Array(~~(v / 2)).fill(mid));
} else if (c > 0) {
v -= c;
left.splice(0, 0, ...new Array(Math.ceil(v / 2)).fill(mid));
right.push(...new Array(~~(v / 2) + c).fill(mid));
} else {
v += c;
left.splice(0, 0, ...new Array(Math.ceil(v / 2) - c).fill(mid));
right.push(...new Array(~~(v / 2)).fill(mid));
}
for (let i = 0; i < l; i++) {
if (i % 2) {
nums[i] = right.shift();
} else {
nums[i] = left.shift();
}
}
return nums;
};