324 Wiggle Sort II
Given an unsorted arraynums
, reorder it such thatnums[0] < nums[1] > nums[2] < nums[3]...
.
Example:
(1) Givennums = [1, 5, 1, 1, 6, 4]
, one possible answer is[1, 4, 1, 5, 1, 6]
.
(2) Givennums = [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?
这题nlogn的解法不难,就是排序,然后把数组中间断开。小的一半放偶数位,大的一半放奇数位就ok了。
解法一:
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;
}
Last updated
Was this helpful?