public static void wiggleSort(int[] nums) {
if (nums == null || nums.length < 2) {
return;
}
int[] tmp = Arrays.copyOf(nums, nums.length);
// this method use nlogn time & n space
Arrays.sort(tmp);
int mid = (nums.length - 1) / 2;
int end = nums.length - 1;
for (int i = 0; i < nums.length; i++) {
nums[i] = (i % 2 == 0) ? tmp[mid--] : tmp[end--];
}
}
follow up:这个难度在于要用quick select找中位数,然后把数组劈开两半。然后跟上面同理可得结果。但普通的quick select是不能通过OJ的,因为我们要保证重复的元素都集中在中间才行。所以quick select里要用3 way partition。这个中间要用一个arraylist来暂存答案,所以用了O(n)space(这题考点太多太崩溃,O(1)space的virtual index wiring简直理解不能,完爆脑容量)
public void wiggleSort(int[] nums) {
if (nums == null || nums.length == 0) {
return;
}
int len = nums.length;
// quick select to find middle point
int mid = quickSelect(nums, len / 2);
if (len % 2 == 0) {
mid = mid - 1;
}
int smInd = mid;
int bgInd = len - 1;
// rearrange the array
ArrayList<Integer> tmp = new ArrayList<>();
for (int i = 0; i < len; i++) {
if (i % 2 == 0) {
tmp.add(nums[smInd--]);
} else {
tmp.add(nums[bgInd--]);
}
}
int ind = 0;
// put result back to the original array
for (Integer elem : tmp) {
nums[ind++] = elem;
}
}
private int quickSelect(int[] nums, int k) {
int start = 0;
int end = nums.length - 1;
int[] bounds = patition(nums, start, end);
while (start < end && (k < bounds[0] || k > bounds[1])) {
if (k < bounds[0]) {
end = bounds[0] - 1;
} else if (k > bounds[1]) {
start = bounds[1] + 1;
}
bounds = patition(nums, start, end);
}
return k;
}
private int[] patition(int[] nums, int start, int end) {
int left = start;
int right = end;
int i = start;
int pivot = nums[left];
while (i <= right) {
if (nums[i] < pivot) {
swap(i, left, nums);
i++;
left++;
} else if (nums[i] == pivot) {
i++;
} else {
swap(i, right, nums);
right--;
}
}
int[] res = new int[2];
res[0] = left;
res[1] = right;
return res;
}
private void swap(int i, int j, int[] nums) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}