LintCode 508: Wiggle Sort
LintCode 508: Wiggle Sort
题目描述
给你一个没有排序的数组,请将原数组就地重新排列满足如下性质
nums[0] <= nums[1] >= nums[2] <= nums[3]....
Thu Feb 23 2017
思路
这道题看起来好像无从下手,但其实思路很简单,方法也有很多种。
第一种方法
先将数组排序,然后将第二个、第三个数交换,第四个、第五个数交换...即可。时间复杂度是\(O(nlogn)\).
第二种方法
第二种方法先找出数字们的中位数,然后将大于中位数的数放在奇数位上,小于中位数的数放在偶数位上。
求中位数算法的时间复杂度可以做到\(O(n)\),即利用快排的思想,对于每一次划分出来的partition,下一次只递归中位数所在的那一半数组。虽然在最坏情况下时间复杂度是\(O(n^2)\),但是平均情况是\(O(n)\).
找到中位数后,由于题目要求只能在原数组上原地排序,不能借用新数组,所以应该还是要利用快排的思想,在数组中分别找到在奇数位但比中位数小的数,以及在偶数位但比中位数大的数,然后两者交换。这个方法在存在很多与中位数相等的数的时候不太好用,待使用更好的解决方案。
第三种方法
上面想了那么多,最后发现原来题目还可以更简单一点。
其实只需要从第1个数开始向后遍历,每次检查当前数与前一个数是否满足大小关系:在奇数位的数要大于偶数位的数。
代码
// 只放第三种方法
void wiggleSort(vector<int>& nums)
{
for(int i = 1; i < nums.size(); ++i)
if((i % 2 == 1 && nums[i] < nums[i - 1])
|| (i % 2 == 0 && nums[i] > nums[i - 1]))
swap(nums[i - 1], nums[i]);
}