Array     C++     Divide and Conquer     Medium     Quickselect     Sorting    

Problem Statement:

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

You may assume the input array always has a valid answer.

 

Example 1:

Input: nums = [1,5,1,1,6,4]
Output: [1,6,1,5,1,4]
Explanation: [1,4,1,5,1,6] is also accepted.

Example 2:

Input: nums = [1,3,2,2,3,1]
Output: [2,3,1,3,1,2]

 

Constraints:

  • 1 <= nums.length <= 5 * 104
  • 0 <= nums[i] <= 5000
  • It is guaranteed that there will be an answer for the given input nums.

 

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

Solution:

My first attempt was to do alternate from front (first even 0,2,4,.. indices then odd 1,3,5,… indices) ie 0,1,2,3,4,5 becomes 0,3,1,4,2,5 and 0,1,2,3,4 becomes 0,3,1,4,2.

 
void wiggleSort(vector<int>& nums) 
{
    int n = nums.size();
    sort(nums.begin(),nums.end());
    vector<int> arr(n, 0);
    for (int i=0; i<n; i+=2)
        arr[n-1-i] = nums[(n+i)/2]; 
    for (int i=1; i<n; i+=2)
        arr[n-1-i] = nums[i/2];
    nums = arr;
}
 

However this fails for 4,5,5,6 because it will give us 4,5,5,6. Notice however that alternate from back works ie 5,6,4,5 (again even indices R to L then odd indices R to L). A few more tests should tell you that this is a valid algorithm. Hence gives us an AC. However we have to take special care of whether array size is even or odd.

 
void wiggleSort(vector<int>& nums) 
{
    int n = nums.size();
    sort(nums.begin(),nums.end());
    vector<int> arr(n, 0);
    for (int i=0; i<n; i+=2)
        arr[i] = nums[(n-i)/2 - (n%2==0 ? 1 : 0)];
    for (int i=1; i<n; i+=2)
        arr[i] = nums[n-1-i/2];
    nums = arr;
}