324. Wiggle Sort II
Given an unsorted array nums, reorder it such that nums[0] < nums[1] > nums[2] < nums[3]…
Example 1:
Input: nums = [1, 5, 1, 1, 6, 4]
Output: One possible answer is [1, 4, 1, 5, 1, 6].
Example 2:
Input: nums = [1, 3, 2, 2, 3, 1]
Output: 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: sort
思路:
先对数组排序,然后找到中位数,用两个pt 从前半段和后半段的末尾交替取数。为什么要这么做呢?对于非重复序列来讲,这只是众多选择中的一种。从下面代码中的例子来看,wiggle1是用这种方法,由两个交替单调递减序列构成。wiggle2由一个单减一个单增构成,这两种都满足题意。但是注意到我们的目的只是让每个数字比它临近的两个数大/小就行了,这里大数被“浪费”在了波动末尾的较小值上。而如果数组中有重复数字,这个方法可能造成前面的波动不够大。比如第二个例子。由于这道题保证了一定有解,那么最保险的做法必须是用大数和大数去比较,才有可能找到解。
Complexity
Time complexity: O(nlogn)
Space complexity: O(n)
// nums [1, 2, 3, 4, 5, 6 ,7, 8, 9, 10 ]
// wiggle1 [5, 10, 4, 9, 3, 8, 2, 7, 1, 6]
// wiggle2 [5, 6, 4, 7, 2, 8, 3, 9, 2, 10, 1]
// nums [1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3]
// wiggle1 [2, 3, 2, 3, 2, 3, 2, 3, 2, 2, 1, 2, 1, 2]
// wiggle2 [2, 2, 2, 2, 2, 2, 3, 2, 3, 2, 3, 1, 3, 1]
class Solution {
public:
void wiggleSort(vector<int>& nums) {
if (nums.empty()) return;
int n = nums.size();
vector<int> tmp = nums;
sort(tmp.begin(), tmp.end());
int pt1 = (n + 1) / 2, pt2 = n;
for (int i = 0; i < n; i ++){
nums[i] = i & 1 ? tmp[--pt2] : tmp[--pt1];
}
return;
}
};
方法2: partition
思路:
discussion:https://leetcode.com/problems/wiggle-sort-ii/discuss/77677/O(n)%2BO(1)-after-median-Virtual-Indexing
class Solution {
public:
/**
* @param nums a list of integer
* @return void
*/
void wiggleSort(vector<int>& nums) {
// Write your code
// Find a median.
if (nums.empty()) return;
int n = nums.size();
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;
if (A(i) > mid){
swap(A(i++), A(j++));
}
else if (A(i) < mid){
swap(A(j), A(k--));
}
else{
j++;
}
}
};