https://leetcode.com/problems/wiggle-sort-ii/
给定一个数组,将其排序成nums[0] < nums[1] > nums[2] < nums[3] ...的次序(摆动排序)
测试用例:
Example 1:
Input: nums = [1, 5, 1, 1, 6, 4]
Output: One possible answer is [1, 4, 1, 5, 1, 6].
Example 2:
Input: nums = [1, 3, 2, 2, 3, 1]
Output: One possible answer is [2, 3, 1, 3, 1, 2].
所谓的摆动的排序其实就是维护一个局部有序的特性:下标为奇数的元素要大于它两边的邻居(如果存在右邻居的话)。
符合摆动排序的数组可以看成两个子数组组成,一个下标为奇数,一个下标为偶数。两个子数组之间存在上面所讲的次序性,这种次序是局部特性,而当奇数子数组的所有元素都大于等于偶数子数组的所有元素,这种特性就上升为全局特性。
具体来说,我将数组排序后分成较小的一半或加一个元素(偶数子数组)、较大的一半(奇数子数组),然后从两个子数组的尾部往前遍历(从前往后的话在中间存在重复元素的情况下会出现奇数子数组的元素等于邻居的错误,比如4, 5, 5, 6),每次添加一个偶数子数组的元素和一个奇数子数组的元素。
class Solution {
public void wiggleSort(int[] nums) {
if (nums == null || nums.length == 0) {
return;
}
//时间:O(nlogn)
Arrays.sort(nums);
//空间:O(n)
int[] arr = new int[nums.length];
System.arraycopy(nums, 0, arr, 0, nums.length);
//偶数子数组的尾元素:数组长度为奇数时为中位数,为偶数时为第一个中位数
int leftEnd = (nums.length % 2 == 1) ? nums.length / 2 : nums.length/2 - 1;
int i = leftEnd, j = nums.length - 1, k = 0;
while (j > leftEnd) {
nums[k++] = arr[i--];
nums[k++] = arr[j--];
}
if (i == 0) {
nums[k] = arr[i];
}
}
}
参考:
https://leetcode.com/problems/wiggle-sort-ii/discuss/77684/Summary-of-the-various-solutions-to-Wiggle-Sort-for-your-reference
https://leetcode.com/problems/wiggle-sort-ii/discuss/77682/Step-by-step-explanation-of-index-mapping-in-Java
https://leetcode.com/problems/wiggle-sort-ii/discuss/77688/O(n)%2BO(1)-after-median-without-Virtual-Indexing-%3A-)
https://leetcode.com/problems/wiggle-sort-ii/discuss/77677/O(n)%2BO(1)-after-median-Virtual-Indexing
https://leetcode.com/problems/wiggle-sort-ii/discuss/77680/Clear-Java-O(n)-avg-time-and-O(n)-space-solution-using-3-way-partition
https://leetcode.com/problems/wiggle-sort-ii/discuss/77681/O(n)-time-O(1)-space-solution-with-detail-explanations
https://leetcode.com/problems/wiggle-sort-ii/discuss/77746/AC-java-solution(7ms)