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?
我的思路:
1.找到中间位置的数,使得左边的数小于中间的数,右边的数大于中间的数,然后对左右两边进行插入。partition函数,平均时间复杂度为O(n). (why??)
如:下面的序号
0 1 2 3 4 5 6 7
0 4 1 5 2 6 3 7
因此,这里的mid = 3, 那么对于<=3的序号,他们的坐标变为 2*i ; 对于右边的坐标变为 i - (len - i) = 2 * i - len;
如:1 -> 2; 2->4; 3->6; 4->1 .....
但是我在这里进行坐标变换时,需要有个len长的数组,标记有没有被访问过; 而且这样进行坐标变换时会循环,需要每次从未标记的数开始再进行转换。比如: 1 -> 2 -> 4 -> 1. 那么这些位置的数字都转换好了,同时遍历标记数组发现3没有转换,再从3开始转换。这样的话空间复杂度为O(n),并不能满足题意。
因此下面这个是大神的做法,我还没看懂坐标转换的方法。这个代码是结合我自己写的partition函数和他的坐标转换的代码。
int partition(vector<int>& number, int begin, int end){
if(number.size() == 1) return number[0];
int index = number[begin];
int low = begin, high = end;
while(low < high){
while((high > low) && (number[high] >= index))
high--;
if(high > low)
number[low++] = number[high];
while((low < high) && (number[low] <= index))
low++;
if(low < high)
number[high--] = number[low];
}
number[low] = index;
return low;
}
void wiggleSort1(vector<int>& nums) {
if(nums.size() <= 1) return;
int len = nums.size();
int begin = 0, end = len-1, mid = begin + (end - begin)/2;
int index = partition(nums, begin, end);
while(index != mid){
if(index < mid)
begin = index + 1;
else
end = index - 1;
index = partition(nums, begin, end);
}
mid = nums[index];
int n = len;
// Index-rewiring.
#define A(i) nums[(1+2*(i)) % (n|1)]
// 3-way-partition-to-wiggly in O(n) time with O(1) space.
int i = 0, j = 0, k = n - 1;
while (j <= k) {
int pos = (1+2*(j)) % (n|1);
if (A(j) > mid)
swap(A(i++), A(j++));
else if (A(j) < mid)
swap(A(j), A(k--));
else
j++;
}
}
当然,他的代码是这样的,这里调用了 nth_element() 函数,时间效率上比我自己写的partition函数快一倍,作用都是一样的。
void wiggleSort(vector<int>& nums) {
int n = nums.size();
// Find a median.
auto midptr = nums.begin() + n / 2;
nth_element(nums.begin(), midptr, nums.end());
int mid = *midptr;
// Index-rewiring.
#define A(i) nums[(1+2*(i)) % (n|1)]
// 3-way-partition-to-wiggly in O(n) time with O(1) space.
int i = 0, j = 0, k = n - 1;
while (j <= k) {
int pos = (1+2*(j)) % (n|1);
if (A(j) > mid)
swap(A(i++), A(j++));
else if (A(j) < mid)
swap(A(j), A(k--));
else
j++;
}
}