[leetcode] 324. Wiggle Sort II 解题报告

63 篇文章 0 订阅
10 篇文章 0 订阅

题目链接:https://leetcode.com/problems/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?


思路:一种比较naive的做法是先对数组进行排序, 然后从左往右奇数索引位置放大于中位数的数, 然后从右往左在偶数索引位置放小于中位数的数, 剩下的位置都放中位数. 其时间复杂度为O(nlog(n)), 空间复杂度为O(n).

代码如下:

class Solution {
public:
    void wiggleSort(vector<int>& nums) {
        if(nums.size()<=1) return;
        sort(nums.begin(), nums.end());
        int len = nums.size(), k = 1, high = (len%2)?len-1:len-2, mid=nums[len/2];
        vector<int> ans(len, mid);
        for(int i = len-1; i >=0 && nums[i]>mid; i--, k+=2)
            ans[k] = nums[i];
        for(int i = 0; i < len && nums[i]<mid; i++, high-=2)
            ans[high] = nums[i];
        nums = ans;
    }
};


显然上面的方法并符合要求, 但却是理解这题的一个先导. 接下来就可以对其进行优化. 

之前我们是独立的插入大于或者小于中位数的数, 现在我们可以同时做, 也就是, 遍历数组的时候如果当前的数大于中位数就将其从左往右放奇数位置, 如果小于中位数就将其从右往左放在偶数位置. 这样还需要解决的一个问题是如何可以互不干扰的放到正确位置. 举个栗子: 1, 1, 2, 2, 2, 3这六个数:

我们可以按照这样一个顺序将数组索引拉开成这样: 1, 3, 5, 0, 2, 4, 也就是我们可以按照这样一个顺序来遍历数组, 同时维护一个低位指针用来代表奇数位置已经放到哪里, 和一个高位指针来表示偶数位置已经放到哪里, 这样在我们遍历数组的每一个元素的时候就可以按照这样的方式将元素分别放高位还是低位. 而要将数组按照这样索引的方式遍历我们只需要一个映射即可, 即(2*i+1)%(len|1).

代码如下:

class Solution {
public:
    void wiggleSort(vector<int>& nums) {
        nth_element(nums.begin(), nums.begin()+nums.size()/2, nums.end());
        int len=nums.size(), low=0, high=len-1, mid =nums[len/2], i=0;
        auto index = [=](int pos){ return (1+pos*2)%(len|1); };
        while(i <= high)
        {
            if(nums[index(i)] > mid) swap(nums[index(i++)], nums[index(low++)]);
            else if(nums[index(i)]<mid) swap(nums[index(i)],nums[index(high--)]);
            else i++;
        }
    }
};
参考:https://leetcode.com/discuss/77133/o-n-o-1-after-median-virtual-indexing

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值