https://leetcode.com/problems/wiggle-sort-ii/
1. 解题思路
先找出数组的中位数,然后for循环遍历数组,大于中位数的放在奇数index上,小于中位数的放在偶数index上。
若数组长度为4,按照:1 3 0 2的顺序遍历
若数组长度为5,按照:1 3 5 0 2的顺序遍历
总结来说就是按照(2i+1)%(n|1)的顺序遍历数组。
注意需要处理多个中位数的情况,此时不能保证中位数应该放在偶数index还是奇数index上,处理方法是先不管直接跳过,放置完所有非中位数的数,中位数怎么放置都可以。
2. AC代码
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
int left=0, right=nums.size()-1;
// k = nums.size() - k;
int mid, i, j;
while(left<right){
if(right-left==1){
if(nums[left]>nums[right]) swap(nums[left], nums[right]);
if(left==k) return nums[left];
else return nums[right];
}
mid = (left+right)/2;
median(nums, left, right, mid);
i = left;
j = right-1;
while(i<j){
while(nums[++i]<nums[right-1]) {}
while(nums[--j]>nums[right-1]) {}
if(i<j) swap(nums[i], nums[j]);
}
swap(nums[right-1], nums[i]);
if(i==k) return nums[i];
else if(k<i) right = i-1;
else left = i+1;
}
return nums[left];
}
void median(vector<int>& nums, int left, int right, int mid){
if(nums[left]>nums[mid]) swap(nums[left], nums[mid]);
if(nums[left]>nums[right]) swap(nums[left], nums[right]);
if(nums[mid]>nums[right]) swap(nums[mid], nums[right]);
swap(nums[mid], nums[right-1]);
}
int new_index(int i, int n){
return (2*i+1) % (n|1);
}
void wiggleSort(vector<int>& nums) {
int n = nums.size();
int mid = findKthLargest(nums, (n-1)/2);
int left = 0, right = n-1, i=0;
while(i<=right){
if(nums[new_index(i, n)]>mid){
swap(nums[new_index(i, n)], nums[new_index(left, n)]);
left++;
i++;
}
else if(nums[new_index(i, n)]<mid){
swap(nums[new_index(i, n)], nums[new_index(right, n)]);
right--;
}
else i++; //这一步非常重要,跳过中位数
}
}
};