(TBD)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?

Solution

這題靠北難,已經看了解答還是不太理解。

大致上的理解是透過kth largest Element那裏得到的方法找到中間值(medium value), 同時array會被切分成兩大部分,左半邊是大於medium value,右半邊是小於medium value。

然後把會想把左半邊的跟右半邊的交叉擺放,就可以得到wiggle array.

把左半邊的都從依序擺放到所有的奇數位置,右半邊的都擺放到偶數位置。即可求解。

重新計算位置的方法是 (1+2*i)%(n|1) , 其中i是本來的位置,n是array的大小。

public void wiggleSort(int[] nums) {
    int n = nums.length, m = (n + 1) >> 1;
    int median = findKthLargest(nums, m);
    
    //TOBEDONE: 這裡的轉換還是不太懂
    for (int i = 0, j = 0, k = n - 1; j <= k;) {
        if (nums[A(j, n)] > median) {
            swap(nums, A(i++, n), A(j++, n));
        } else if (nums[A(j, n)] < median) {
            swap(nums, A(j, n), A(k--, n));
        } else {
            j++;
        }
    }
}

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

 public int findKthLargest(int[] nums, int k) {
        shuffle(nums);
        return quickSelect(nums, 0, nums.length-1,  k-1);
    }
    
    public void shuffle(int[] nums){
        for(int i = 0 ; i < nums.length; i++){
            swap(nums, i, (int)(Math.random()*(nums.length-1)));
        }
    }
    
    public int quickSelect(int[] nums, int start, int end, int k){
        int left = start;
        int pivot = nums[end];
        for(int i = start; i < end; i++){
            if(pivot < nums[i]){
                swap(nums, left, i);
                left++;
            }
        }
        swap(nums, left, end);
        if(left == k){
            return pivot;
        }
        else if (left < k){
            //k is on the right ride
            return quickSelect(nums, left+1, end, k);
        }
        else {
            //k is on the left ride
            return quickSelect(nums, start, left-1, k);
        }
    }
    
    public void swap(int[] nums, int i, int j){
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

Last updated

Was this helpful?