Skip to content

324. Wiggle Sort II

Problem:

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?

Solutions:

public class Solution {
    public void wiggleSort(int[] nums) {
        int[] tmp = new int[nums.length];
        Arrays.sort(nums);
        int left = (nums.length - 1) / 2, right = nums.length - 1;
        for (int i = 0; i < tmp.length; i ++) {
            if (i % 2 == 0) {
                tmp[i] = nums[left--];
            }
            else {
                tmp[i] = nums[right--];
            }
        }
        for (int i = 0; i < tmp.length; i ++) {
            nums[i] = tmp[i];
        }
    }
}
public class Solution {
    public void wiggleSort(int[] nums) {
        int median = quickSelect(nums, 0, nums.length - 1, (nums.length + 1)/ 2);
        int i = 0, j = 0, k = nums.length - 1;
        while (i <= k) {
            int it = index(i, nums.length), jt = index(j, nums.length), kt = index(k, nums.length);
            if (nums[it] > median) {
                int tmp = nums[it];
                nums[it] = nums[jt];
                nums[jt] = tmp;
                i ++;
                j ++;
            }
            else if (nums[it] < median) {
                int tmp = nums[it];
                nums[it] = nums[kt];
                nums[kt] = tmp;
                k --;
            }
            else {
                i ++;
            }
        }
    }
    private int index(int i, int n) {
        if (i < n /2) {
            return i * 2 + 1;
        }
        else {
            return (i - n / 2) * 2;
        }
    }
    private int partition(int[] nums, int left, int right) {
        int x = nums[right];
        int i = left;
        int j = right - 1;
        while (i <= j) {
            if (nums[i] <= x) {
                i ++;
            }
            else {
                if (nums[j] > x) {
                    j --;
                }
                else {
                    int tmp = nums[i];
                    nums[i] = nums[j];
                    nums[j] = tmp;
                    i ++;
                    j --;
                }
            }
        }
        nums[right] = nums[i];
        nums[i] = x;
        return i;
    }
    private int quickSelect(int[] nums, int left, int right, int i) {
        if (left == right) {
            return nums[left];
        }
        int q = partition(nums, left, right);
        int k = q - left + 1;
        if (i == k){
            return nums[q];
        }
        else if (i < k) {
            return quickSelect(nums, left, q - 1, i);
        }
        else {
            return quickSelect(nums, q + 1, right, i - k);
        }
    }
}