利用中位数的概念,中位数就是将一组数分成2等份(若为奇数,则中位数既不属于左也不属于右,所以是2等份),其一组数中任何一个元素都大于等于另一组数
那么我们是不是只要一左一右配合着插入,就保证了差值+-+-+-的要求?
由于题目输入限制了,必定存在解,所以此处我们不需要担心如果重复中位数太多,出现一左一右相等的情况
算法步骤:
1)找到中位数
利用lc215 Kth Largest...,将k=(nums.length+1) / 2,可以在o(n)内求出中位数
2)一左一右插入
0 2 4 .. 插大于中位数的
1 3 5 .. 插小于中位数的
考虑到中位数可能有重复的情况
我们从后往前插入小于中位数的值
从前往后插入大于中位数的值
剩下的空位补上中位数
代码中为了省事找中位数的部分用的o(klogn)的方法,详情可以看之前博客
1 class Solution { 2 public void wiggleSort(int[] nums) { 3 int median = findKthLargest(nums, (nums.length+1) / 2); 4 int left = 1; 5 int right = nums.length % 2 == 0 ? nums.length-2 : nums.length-1; 6 7 int[] tmp = new int[nums.length]; 8 for(int i=0; i<nums.length; i++){ 9 if(nums[i] > median){ 10 tmp[left] = nums[i]; 11 left += 2; 12 }else if(nums[i] < median){ 13 tmp[right] = nums[i]; 14 right -= 2; 15 } 16 } 17 18 while(left < nums.length){ 19 tmp[left] = median; 20 left += 2; 21 } 22 while(right >= 0){ 23 tmp[right] = median; 24 right -= 2; 25 } 26 27 System.arraycopy(tmp, 0, nums, 0, nums.length); 28 } 29 public int findKthLargest(int[] nums, int k) { 30 if(nums.length == 0) 31 return 0; 32 PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder()); 33 int res = 0; 34 for(int num : nums) 35 pq.offer(num); 36 37 while(k != 0){ 38 res = pq.poll(); 39 k--; 40 } 41 42 return res; 43 } 44 45 }