zoukankan      html  css  js  c++  java
  • Leetcode: Wiggle Sort II

    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?

    这道题应该是hard,首先思想上面参考了https://discuss.leetcode.com/topic/32861/3-lines-python-with-explanation-proof

    I put the smaller half of the numbers on the even indexes and the larger half on the odd indexes, both from right to left:

    Example nums = [1,2,...,7]      Example nums = [1,2,...,8] 
    
    Small half:  4 . 3 . 2 . 1      Small half:  4 . 3 . 2 . 1 .
    Large half:  . 7 . 6 . 5 .      Large half:  . 8 . 7 . 6 . 5
    --------------------------      --------------------------
    Together:    4 7 3 6 2 5 1      Together:    4 8 3 7 2 6 1 5
    

    I want:

    • Odd-index numbers are larger than their neighbors.

    Since I put the larger numbers on the odd indexes, clearly I already have:

    • Odd-index numbers are larger than or equal to their neighbors.

    Could they be "equal to"? That would require some number M to appear both in the smaller and the larger half. It would be the largest in the smaller half and the smallest in the larger half. Examples again, where S means some number smaller than M and L means some number larger than M.

    Small half:  M . S . S . S      Small half:  M . S . S . S .
    Large half:  . L . L . M .      Large half:  . L . L . L . M
    --------------------------      --------------------------
    Together:    M L S L S M S      Together:    M L S L S L S M
    

    You can see the two M are quite far apart. Of course M could appear more than just twice, for example:

    Small half:  M . M . S . S      Small half:  M . S . S . S .
    Large half:  . L . L . M .      Large half:  . L . M . M . M
    --------------------------      --------------------------
    Together:    M L M L S M S      Together:    M L S M S M S M
    

    You can see that with seven numbers, three M are no problem. And with eight numbers, four M are no problem. Should be easy to see that in general, with n numbers, floor(n/2) times M is no problem. Now, if there were more M than that, then my method would fail. But... it would also be impossible:

    • If n is even, then having more than n/2 times the same number clearly is unsolvable, because you'd have to put two of them next to each other, no matter how you arrange them.
    • If n is odd, then the only way to successfully arrange a number appearing more than floor(n/2) times is if it appears exactly floor(n/2)+1 times and you put them on all the even indexes. And to have the wiggle-property, all the other numbers would have to be larger. But then we wouldn't have an M in both the smaller and the larger half.

    So if the input has a valid answer at all, then my code will find one.

    然后根据https://discuss.leetcode.com/topic/41464/step-by-step-explanation-of-index-mapping-in-java

    Assume your original array is {6,13,5,4,5,2}. After you get median element, the 'nums' is partially sorted such that the first half is larger or equal to the median, the second half is smaller or equal to the median, i.e

    13   6   5   5   4   2
    
             M
    

    In the post https://leetcode.com/discuss/76965/3-lines-python-with-explanation-proof, we have learned that , to get wiggle sort, you want to put the number in the following way such that

    (1) elements smaller than the 'median' are put into the even slots(starting from right, left side may have left-overs, which will be stuffed by median)

    (2) elements larger than the 'median' are put into the odd slots(starting from left, right side may have left-overs, which will be filled by median number)

    (3) the medians are put into the remaining slots.

    Index :       0   1   2   3   4   5
    Small half:   M       S       S    
    Large half:       L       L       M
    

    M - Median, S-Small, L-Large. In this example, we want to put {13, 6, 5} in index 1,3,5 and {5,4,2} in index {0,2,4}

    可惜每太看懂O(1)space的方法,我的方法用了O(N)space

     1 public class Solution {
     2     public void wiggleSort(int[] nums) {
     3         int median = findKthLargest(nums, (nums.length+1)/2);
     4         int odd = 1, even = (nums.length%2==0? nums.length-2 : nums.length-1);
     5         int[] arr = new int[nums.length];
     6         for (int num : nums) {
     7             if (num > median) {
     8                 arr[odd] = num;
     9                 odd += 2;
    10             }
    11             else if (num < median) {
    12                 arr[even] = num;
    13                 even -= 2;
    14             }
    15         }
    16         while (odd < arr.length) {
    17             arr[odd] = median;
    18             odd += 2;
    19         }
    20         while (even >= 0) {
    21             arr[even] = median;
    22             even -= 2;
    23         }
    24         for (int i=0; i<arr.length; i++) {
    25             nums[i] = arr[i];
    26         }
    27     }
    28     
    29     public int findKthLargest(int[] nums, int k) {
    30         int len = nums.length;
    31         return findKthSmallest(nums, 0, len-1, len-k+1);
    32     }
    33     
    34     public int findKthSmallest(int[] nums, int start, int end, int k) {
    35         int l = start;
    36         int r = end;
    37         int pivot = end;
    38         while (l < r) {
    39             while (l<r && nums[l] < nums[pivot]) {
    40                 l++;
    41             }
    42             while (l<r && nums[r] >= nums[pivot]) {
    43                 r--;
    44             }
    45             if (l == r) break;
    46             swap(nums, l, r);
    47         }
    48         swap(nums, l, pivot);
    49         if (l+1 == k) return nums[l];
    50         else if (l+1 < k) return findKthSmallest(nums, l+1, end, k);
    51         else return findKthSmallest(nums, start, l-1, k);
    52     }
    53     
    54     public void swap(int[] nums, int l, int r) {
    55         int temp = nums[l];
    56         nums[l] = nums[r];
    57         nums[r] = temp;
    58     }
    59 }
  • 相关阅读:
    mysql日期转化
    跳来跳去,到底去大公司还是小公司?
    年度重大升级,IntelliJ IDEA 2019.2 稳定版发布
    3年Java,鏖战腾讯
    重磅!挑战Oracle,华为将开源 GaussDB 数据库
    厉害了,Java EE 再次更名为 Jakarta EE
    彻底干掉恶心的 SQL 注入漏洞, 一网打尽!
    PostgreSQL 荣获 2019 年 O'Reilly 终身成就奖
    Intellij IDEA 智能补全的 10 个姿势,简直不能太牛逼!
    注意,千万不要打断工作中的程序员
  • 原文地址:https://www.cnblogs.com/EdwardLiu/p/6181802.html
Copyright © 2011-2022 走看看