Google 2016 面试题3 | 摆动排序 II

题目描述

给出一个整数数组nums,重新排列nums使得nums[0] < nums[1] > nums[2] < nums[3]…
Example:
nums = [1, 5, 1, 1, 6, 4], 一个可能的答案是[1, 4, 1, 5, 1, 6]
数据保证必定有解。

分析解答

解法I O(nlogn)时间排序+O(n)空间辅助数组解法:

  1. 对原数组排序,得到排序后的辅助数组tmp

  2. 对原数组的偶数位下标填充tmp的末尾元素

  3. 对原数组的奇数位下标填充tmp的末尾元素

算法复杂度是快速排序的复杂度O(NlogN)。

void wiggleSort(vector<int>& nums) {
    int sz = nums.size();
    sort(nums.begin(), nums.end());
    vector<int> tmp = nums;
    int k = sz - 1;
    for (int i=1; i<sz; i+=2)
        nums[i] = tmp[k--];
    for (int i=0; i<sz; i+=2)
        nums[i] = tmp[k--];
}

解法II O(n)时间复杂度+O(1)空间复杂度解法:

  1. 使用O(n)时间复杂度的quickSelect算法,从未经排序的数组nums中选出中位数mid

  2. 参照解法I的思路,将nums数组的下标x通过函数idx()从[0, 1, 2, … , n - 1, n] 映射到 [1, 3, 5, … , 0, 2, 4, …],得到新下标ix

  3. 以中位数mid为界,将大于mid的元素排列在ix的较小部分,而将小于mid的元素排列在ix的较大部分。

思路来源:https://discuss.leetcode.com/topic/32929/o-n-o-1-after-median-virtual-indexing

void wiggleSort(vector<int>& nums) {
    int n = nums.size();

    // Find a median.
    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;
    while (j <= k) {
        if (A(j) > mid)
            swap(A(i++), A(j++));
        else if (A(j) < mid)
            swap(A(j), A(k--));
        else
            j++;
    }
}

3-way-partition

详见维基百科

伪码:

procedure three-way-partition(A : array of values, mid : value):
    i ← 0
    j ← 0
    n ← size of A - 1

    while j ≤ n:
        if A[j] < mid:
            swap A[i] and A[j]
            i ← i + 1
            j ← j + 1
        else if A[j] > mid:
            swap A[j] and A[n]
            n ← n - 1
        else:
            j ← j + 1
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值