题目描述:
给定一个无序的数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]… 的顺序。
示例 1:
输入: nums = [1, 5, 1, 1, 6, 4]
输出: 一个可能的答案是 [1, 4, 1, 5, 1, 6]
示例 2:
输入: nums = [1, 3, 2, 2, 3, 1]
输出: 一个可能的答案是 [2, 3, 1, 3, 1, 2]
说明:
你可以假设所有输入都会得到有效的结果。
进阶:
你能用 O(n) 时间复杂度和 / 或原地 O(1) 额外空间来实现吗?
方法1:
主要思路:
(1)将原来的数组进行排序;
(2)然后将排序后的数组分成前后两个部分,为了能够避免中间重复元素的影响,前后两个部分都从后向前遍历,依次放入数组中;
(3)注意若是奇数个元素,则前半部分可以多分得一个元素进行排序;
class Solution {
public:
void wiggleSort(vector<int>& nums) {
vector<int> tmp=nums;
sort(tmp.begin(),tmp.end());//对数组进行排序
//将数组分成前后两部分
int mid=tmp.size()/2;
if(tmp.size()%2==0){//若数组元素的个数是偶数个
--mid;
}
//将前后两部分元素依次放入到数组中
int left=mid;
int right=nums.size()-1;
int pos=0;
while(left>=0){
nums[pos++]=tmp[left--];
if(right>mid){//避免越界多放
nums[pos++]=tmp[right--];
}
}
return;
}
方法2:
主要思路:
(1)从方法1中可以看出,分割前后两部分,重要的是找出中间元素,再保证前半部分的元素小于中间元素,后半部分的元素大于中间元素,而其内部顺序不重要;
(2)故可以先找出中间元素,然后使用中间元素将数组分成两部分,再进行赋值操作;
class Solution {
public:
void wiggleSort(vector<int>& nums) {
vector<int> tmp=nums;//辅助数组
int mid=nums.size()/2;
nth_element(tmp.begin(),tmp.begin()+mid,tmp.end());//找出中间元素
//将数组元素分成前后两个部分
int left=0;
int pos=0;
int right=tmp.size()-1;
while(pos<right){
if(tmp[pos]>tmp[mid]){
swap(tmp[pos],tmp[right--]);
}
else {
if(tmp[pos]<tmp[mid]){
swap(tmp[pos],tmp[left++]);
}
++pos;
}
}
if(tmp.size()%2==0){//偶数的情形
--mid;
}
//将数组的元素进行赋值
left=mid;
right=tmp.size()-1;
pos=0;
while(left>=0){
nums[pos++]=tmp[left--];
if(right>mid){
nums[pos++]=tmp[right--];
}
}
return ;
}
};