思路
首先仿照快速排序找出数组的中位数mid,这里平均复杂度O(n),最坏复杂度O(n^2)。
对数组下标作映射(假设数组长度为6):
0 => 1
1 => 3
2 => 5
3 => 0
4 => 2
5 => 4
则把大于mid的数分配给1,3,5,小于mid的数分给0,2,4,完成
注意:
为了防止有相邻两个数都等于中位数的问题,这里有一个分配的技巧:
1、对于0,2,4,将数组元素小于mid的放在前面,这样中位数只会出现在最后一个
2、对于1,3,5,将数组元素大于mid的放在后面,这样中位数只会出现在第一个
如此,中位数不会相邻:
public class Solution {
public int vi(int n, int original) {
int virtual = (1+ 2 *original)%(n|1);
return virtual;
}
public void wiggleSort(int[] nums) {
int len = nums.length;
int median = findMedian(nums);
int i=0, j=0, k=nums.length-1;
while(j<=k) {
if(nums[vi(len,j)]>median) {
swap(nums, vi(len,i++), vi(len,j++));
}else if(nums[vi(len,j)]<median) {
swap(nums, vi(len,k--), vi(len,j));
}else{
j++;
}
}
}
public int findMedian(int[] nums) {
int len = nums.length;
if(len%2 == 0) {
return (findK(nums, len/2, 0, len-1) + findK(nums, len/2-1, 0, len-1))/2;
}else {
return findK(nums, len/2, 0, len-1);
}
}
public int findK(int[] nums, int k, int s, int e) {
if(s>=e) return nums[s];
int m = partition(nums, s, e);
if(m == k) return nums[m];
else if(m<k) {
return findK(nums, k, m+1, e);
}else {
return findK(nums, k, s, m-1);
}
}
public int partition(int[] nums, int i, int j) {
int pivot = nums[i];
int m = i;
int n = i+1;
while(n<=j) {
if(nums[n]<pivot){
swap(nums, ++m, n);
}
n++;
}
swap(nums, i,m);
return m;
}
public void swap(int[] nums, int a, int b) {
int temp = nums[a];
nums[a] = nums[b];
nums[b] = temp;
}
}