324. Wiggle Sort II

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++;
        }
    }
};

 

posted @ 2017-10-08 19:15  Tsunami_lj  阅读(136)  评论(0编辑  收藏  举报