• 324. 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?
    
    Credits:
    Special thanks to @dietpepsi for adding this problem and creating all test cases.

     

    Let's say nums is [10,11,...,19]. Then after nth_element and ordinary partitioning, we might have this (15 is my median):

    index:     0  1  2  3   4   5  6  7  8  9
    number:   18 17 19 16  15  11 14 10 13 12
    

    I rewire it so that the first spot has index 5, the second spot has index 0, etc, so that I might get this instead:

    index:     5  0  6  1  7  2  8  3  9  4
    number:   11 18 14 17 10 19 13 16 12 15
    

    And 11 18 14 17 10 19 13 16 12 15 is perfectly wiggly. And the whole partitioning-to-wiggly-arrangement (everything after finding the median) only takes O(n) time and O(1) space.


    If the above description is unclear, maybe this explicit listing helps:

    Accessing A(0) actually accesses nums[1].
    Accessing A(1) actually accesses nums[3].
    Accessing A(2) actually accesses nums[5].
    Accessing A(3) actually accesses nums[7].
    Accessing A(4) actually accesses nums[9].
    Accessing A(5) actually accesses nums[0].
    Accessing A(6) actually accesses nums[2].
    Accessing A(7) actually accesses nums[4].
    Accessing A(8) actually accesses nums[6].
    Accessing A(9) actually accesses nums[8].

    不需要排序,只需要 partitioning. 正确 partition 的数组只
    要按照这个顺序插入,都是正确的。

    于是问题就分成了三个子问题:
    怎么 partitioning
    什么顺序穿插
    如何 in-place

    空间优化:

    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 newIndex(int index, int n) {
            return (1 + 2*index) % (n | 1);
        }
    

      

      O(n) O(n)
    
    public class Solution {
        public void wiggleSort(int[] nums) {
            int median = findKthLargest(nums, (nums.length+1)/2);
            int odd = 1, even = (nums.length%2==0? nums.length-2 : nums.length-1);
            int[] arr = new int[nums.length];
            for (int num : nums) {
                if (num > median) {
                    arr[odd] = num;
                    odd += 2;
                }
                else if (num < median) {
                    arr[even] = num;
                    even -= 2;
                }
            }
            while (odd < arr.length) {
                arr[odd] = median;
                odd += 2;
            }
            while (even >= 0) {
                arr[even] = median;
                even -= 2;
            }
            for (int i=0; i<arr.length; i++) {
                nums[i] = arr[i];
            }
        }
        
        public int findKthLargest(int[] nums, int k) {
            int len = nums.length;
            return findKthSmallest(nums, 0, len-1, len-k+1);
        }
        
        public int findKthSmallest(int[] nums, int start, int end, int k) {
            int l = start;
            int r = end;
            int pivot = end;
            while (l < r) {
                while (l<r && nums[l] < nums[pivot]) {
                    l++;
                }
                while (l<r && nums[r] >= nums[pivot]) {
                    r--;
                }
                if (l == r) break;
                swap(nums, l, r);
            }
            swap(nums, l, pivot);
            if (l+1 == k) return nums[l];
            else if (l+1 < k) return findKthSmallest(nums, l+1, end, k);
            else return findKthSmallest(nums, start, l-1, k);
        }
        
        public void swap(int[] nums, int l, int r) {
            int temp = nums[l];
            nums[l] = nums[r];
            nums[r] = temp;
        }
    }
    

      

      

    A(i) = nums[(1+2*(i)) % (n|1)] -----------(n|1) 强行变奇数 

     

  • 相关阅读:
    洛谷 P1972 [SDOI2009]HH的项链
    洛谷P1494 BZOJ2038【国家集训队】小Z的袜子
    联合体以及如何调出内存窗口
    利用C语言结构体模拟一个简单的JavaBean
    结构体赋值
    C语言结构体赋值2
    结构体所占内存大小
    C语言结构体的引入
    堆的申请和释放2
    堆的申请和释放
  • 原文地址:https://www.cnblogs.com/apanda009/p/7173037.html
Copyright © 2020-2023  润新知