Question

Formatted question description: https://leetcode.ca/all/324.html

 324	Wiggle Sort II

 Given an unsorted array nums, reorder it such that 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].


 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?

 @tag-array

Algorithm

Sort the array first, and then make adjustments.

The adjustment method is to find the number in the middle of the array, which is equivalent to dividing the ordered array into two parts from the middle.

Then take one from the end of the first half, and go one from the end of the second half, so that the first number is less than the second number.

Then take the second to last from the first half and take the second to last from the second half. This ensures that the second number is greater than the third number and the third number is less than the fourth number.

And so on until all of them are processed.

Code

Java

  • import java.util.Arrays;
    
    public class Wiggle_Sort_II {
    
        public static void main(String[] args) {
            Wiggle_Sort_II out = new Wiggle_Sort_II();
            Solution_NlogN s = out.new Solution_NlogN();
    
            s.wiggleSort(new int[]{1, 5, 1, 1, 6, 4});
        }
    
        // test: [1,5,1,1,6,4]
        // result: [1,6,1,5,1,4]
        class Solution_NlogN {
            public void wiggleSort(int[] nums) {
    
                if (nums == null || nums.length <= 1) {
                    return;
                }
    
                Arrays.sort(nums);
    
                int[] temp = new int[nums.length];
    
                int left = (nums.length - 1) / 2;
                int right = nums.length - 1;
                // int p = temp.length - 1; // @note: NOT from end index to 0, to avoid tie situation
                int p = 0;
    
                // while (p >= 0) {
                while (p < temp.length) {
                    // if (nums[p] % 2 == 0) {
                    if (p % 2 == 0) {
                        temp[p++] = nums[left--];
                    } else {
                        temp[p++] = nums[right--];
                    }
                }
    
                System.arraycopy(temp, 0, nums, 0, nums.length);
            } // 1,1,1,4,5,6 // 4,5,5,6
        }
    
    
        // divide and conquer
        public class Solution_oN {
            public void wiggleSort(int[] nums) {
                if (nums == null || nums.length <= 1) {
                    return;
                }
    
                int n = nums.length;
    
                // Step 1: Find median of the array, return the index of the median
                int median = findMedian(nums, 0, n - 1, (n - 1) / 2);
    
                // Step 2: 3-way sort, put median in the middle,
                // numbers less than median on the left,
                // numbers greater than median on the right
                int[] temp = new int[n];
                int left = 0;
                int right = n - 1;
    
                for (int i = 0; i < n; i++) {
                    if (nums[i] < nums[median]) {
                        temp[left] = nums[i];
                        left++;
                    } else if (nums[i] > nums[median]) {
                        temp[right] = nums[i];
                        right--;
                    }
                }
    
                // add median into the middle
                for (int i = left; i <= right; i++) {
                    temp[i] = nums[median];
                }
    
                // Step 3: wiggle sort
                left = (n - 1) / 2;
                right = n - 1;
    
                for (int i = 0; i < n; i++) {
                    if ((i & 1) == 0) {
                        nums[i] = temp[left];
                        left--;
                    } else {
                        nums[i] = temp[right];
                        right--;
                    }
                }
            }
    
            private int findMedian(int[] nums, int lo, int hi, int k) {
                if (lo >= hi) {
                    return lo;
                }
    
                int pivot = partition(nums, lo, hi);
                if (pivot == k) {
                    return pivot;
                }
    
                if (pivot > k) {
                    return findMedian(nums, lo, pivot - 1, k);
                } else {
                    return findMedian(nums, pivot + 1, hi, k);
                }
            }
    
            // first half is larger than pivot-value
            private int partition(int[] nums, int lo, int hi) {
                int pivot = nums[lo];
                int i = lo + 1;
                int j = hi;
    
                while (i <= j) {
                    while (i <= j && nums[i] < pivot) {
                        i++;
                    }
    
                    while (i <= j && nums[j] >= pivot) {
                        j--;
                    }
    
                    if (i <= j) {
                        swap(nums, i, j);
                    }
                }
    
                swap(nums, lo, j);
    
                return j;
            }
    
            private void swap(int[] nums, int i, int j) {
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j] = temp;
            }
        }
    }
    
  • // O(n) space
    class Solution {
    public:
        void wiggleSort(vector<int>& nums) {
            vector<int> tmp = nums;
            int n = nums.size(), k = (n + 1) / 2, j = n; 
            sort(tmp.begin(), tmp.end());
            for (int i = 0; i < n; ++i) {
                nums[i] = i & 1 ? tmp[--j] : tmp[--k];
            }
        }
    };
    
  • import random
    
    
    class Solution(object):
      def wiggleSort(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        if len(nums) <= 2:
          nums.sort()
          return
        numscopy = nums + []
        mid = self.quickselect(0, len(nums) - 1, nums, len(nums) / 2 - 1)
        ans = [mid] * len(nums)
        if len(nums) % 2 == 0:
          l = len(nums) - 2
          r = 1
          for i in range(0, len(nums)):
            if nums[i] < mid:
              ans[l] = nums[i]
              l -= 2
            elif nums[i] > mid:
              ans[r] = nums[i]
              r += 2
        else:
          l = 0
          r = len(nums) - 2
          for i in range(0, len(nums)):
            if nums[i] < mid:
              ans[l] = nums[i]
              l += 2
            elif nums[i] > mid:
              ans[r] = nums[i]
              r -= 2
        for i in range(0, len(nums)):
          nums[i] = ans[i]
    
      def quickselect(self, start, end, A, k):
        if start == end:
          return A[start]
    
        mid = self.partition(start, end, A)
    
        if mid == k:
          return A[k]
        elif mid > k:
          return self.quickselect(start, mid - 1, A, k)
        else:
          return self.quickselect(mid + 1, end, A, k)
    
      def partition(self, start, end, A):
        left, right = start, end
        pivot = A[left]
        while left < right:
          while left < right and A[right] <= pivot:
            right -= 1
          A[left] = A[right]
          while left < right and A[left] >= pivot:
            left += 1
          A[right] = A[left]
        A[left] = pivot
        return left
    
    

All Problems

All Solutions