Wiggle Sort II - Medium - L - Star

1 minute read

Published:

Question

  • https://leetcode.com/problems/house-robber-iii/

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.

Approach

  • Median finding
  • https://evelynn.gitbooks.io/google-interview/content/wiggle_sort_ii.html

Solution

class Solution {
    public void wiggleSort(int[] nums) {
        int median = findKthLargest(nums, (nums.length + 1) / 2);
        int n = nums.length;

        int left = 0, i = 0, right = n - 1;

        while (i <= right) {

            if (nums[newIndex(i,n)] > median) {
                swap(nums, newIndex(left++,n), newIndex(i++,n));
            }
            else if (nums[newIndex(i,n)] < median) {
                swap(nums, newIndex(right--,n), newIndex(i,n));
            }
            else {
                i++;
            }
        }
    }
    
    private int findKthLargest(int[] nums, int k) {

        k = nums.length - k;
        int lo = 0;
        int hi = nums.length - 1;
        while (lo < hi) {
            final int j = partition(nums, lo, hi);
            if(j < k) {
                lo = j + 1;
            } else if (j > k) {
                hi = j - 1;
            } else {
                break;
            }
        }
        return nums[k];
    }

    private int partition(int[] nums, int left, int right) {

        int i = left;
        int j = right + 1;
        while(true) {
            while(i < right && nums[++i] < nums[left]);
            while(j > left && nums[left] < nums[--j]);
            if(i >= j) {
                break;
            }
            swap(nums, i, j);
        }
        swap(nums, left, j);
        return j;
    }

    private int newIndex(int index, int n) {
        return (1 + 2*index) % (n | 1);
    }

    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}