1. 程式人生 > >324. Wiggle Sort II

324. Wiggle Sort II

pla vector 如何 num hat else 1-n fin 一起

Given an unsorted array nums, reorder it such that nums[0] < nums[1] > nums[2] < nums[3]....

Example:
(1) Given nums = [1, 5, 1, 1, 6, 4], one possible answer is [1, 4, 1, 5, 1, 6].
(2) Given nums = [1, 3, 2, 2, 3, 1], one possible answer is [2, 3, 1, 3, 1, 2].

Note:
You may assume all input has valid answer.

Follow Up:
Can you do it in O(n) time and/or in-place with O(1) extra space?

解題思路:巨惡心的一題。首先最容易想到的辦法是把數組排好序,然後從中間分開,把兩端分別從大到小開始填充,這樣肯定是可以滿足wiggle的。但是排序的算法肯定是O(nlogn)的。不過可以借鑒著思路。先通過隨機選擇算法取得中間值,然後把大於中間值的往奇數位從前往後填充,小於中間值的往偶數位從後往前填充,這樣等於中間值的數就會被分配到整個數組的偶數位前部分和奇數位後部分,剛好錯開而不是連在一起。所以問題的難點變成了如何把當前的數放到相應的位置上去。通過(1+2*(i)) % (n|1)可以將一個1-n的序列分成1,3,5...,0,2,4,6...於是就可以按照我們開始的想法開始填充了。

class Solution {
public:
    void wiggleSort(vector<int>& nums) {
        int n = nums.size();
        auto midptr = nums.begin() + n / 2;
        nth_element(nums.begin(), midptr, nums.end());
        int mid = *midptr;
        #define A(i) nums[(1+2*(i)) % (n|1)]
        int low = 0, high = n-1
, i = 0; while(i <= high){ if(A(i) > mid) { swap(A(i++), A(low++)); } else if(A(i) < mid) { swap(A(i), A(high--)); } else i++; } } };

324. Wiggle Sort II