Wednesday, May 11, 2016

LeetCode Q324: Wiggle Sort II

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?

Solution:
Please refer to this post

class Solution {
public:
void wiggleSort(vector<int>& nums) {
int n = nums.size();
int mid = n/2;
nth_element(nums.begin(), nums.begin() + mid, nums.end());
threeWayPartition(nums, nums[mid]);
vector<int> res(n);
int largeStart = n-1;
int smallStart = (n%2) ? mid : (mid-1);
for (int i = 0; i < n; i+=2)
res[i] = nums[smallStart--];
for (int i = 1; i < n; i+=2)
res[i] = nums[largeStart--];
nums = res;
}
// this ensures all values equal to the median is in the middle
void threeWayPartition(vector<int> &nums, int val) {
int i = 0, j = 0;
int n = nums.size()-1;
while (j <= n){
if (nums[j] < val)
swap(nums[i++], nums[j++]);
else if (nums[j] > val)
swap(nums[j], nums[n--]);
else
j++;
}
}
};
view raw Q324.cpp hosted with ❤ by GitHub

常数空间的解法:
void wiggleSort(vector<int>& nums) {
if (nums.empty()) {
return;
}
int n = nums.size();
// Step 1: Find the median
vector<int>::iterator nth = next(nums.begin(), n / 2);
nth_element(nums.begin(), nth, nums.end());
int median = *nth;
// Step 2: Tri-partie partition within O(n)-time & O(1)-space.
auto m = [n](int idx) { return (2 * idx + 1) % (n | 1); };
int first = 0, mid = 0, last = n - 1;
while (mid <= last) {
//可以把Tri-partie好的数组想象成一个隐形的数组,
//在Tri-partie好数组之后,就可以利用(2 * idx + 1) % (n | 1)来填数字了
if (nums[m(mid)] > median) {
swap(nums[m(first)], nums[m(mid)]);
++first;
++mid;
}
else if (nums[m(mid)] < median) {
swap(nums[m(mid)], nums[m(last)]);
--last;
}
else {
++mid;
}
}
}
view raw Q324Rnd3.cpp hosted with ❤ by GitHub

No comments:

Post a Comment