507.Wiggle Sort II-摆动排序 II(中等题)

本文介绍了一种名为摆动排序II的数组重排列算法,该算法的目标是将数组按特定顺序排列,使得相邻元素满足特定大小关系。文章详细解释了实现步骤,包括使用快速选择算法寻找中位数的方法,并提供了完整的Java代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

摆动排序 II

  1. 题目

    给你一个数组nums,将它重排列如下形式
    nums[0] < nums[1] > nums[2] < nums[3]….

    注意事项
    你可以认为每个输入都有合法解

  2. 样例

    给出 nums = [1, 5, 1, 1, 6, 4],一种方案为 [1, 4, 1, 5, 1, 6].
    给出 nums = [1, 3, 2, 2, 3, 1],一种方案为 [2, 3, 1, 3, 1, 2].

  3. 挑战

    O(N)时间复杂度 O(1)额外空间

  4. 题解

    1.先使用快速选择算法(算法导论9.2节)获取中位数。
    2.如数组长度为奇数,则将比中位数小的元素放在0,2,4,…位置,比中位数大的放在length-2,length-4,…位置。
    3.如数组长度为偶数,则将比中位数小的元素放在length-2,length-4,…位置,比中位数大的依次放在1,3,5,…位置,剩余位置补中位数。

public class Solution
{
    public static void wiggleSort(int[] nums)
    {
        int[] tem = new int[nums.length];
        for (int i = 0; i < nums.length; i++)
        {
            tem[i] = nums[i];
        }
        int mid = partition(tem, 0, nums.length - 1, nums.length / 2);
        int[] ans = new int[nums.length];
        for (int i = 0; i < nums.length; i++)
        {
            ans[i] = mid;
        }
        int l, r;
        if (nums.length % 2 == 0)
        {
            l = nums.length - 2;
            r = 1;
            for (int i = 0; i < nums.length; i++)
            {
                if (nums[i] < mid)
                {
                    ans[l] = nums[i];
                    l -= 2;
                }
                else if (nums[i] > mid)
                {
                    ans[r] = nums[i];
                    r += 2;
                }
            }
        }
        else
        {
            l = 0;
            r = nums.length - 2;
            for (int i = 0; i < nums.length; i++)
            {
                if (nums[i] < mid)
                {
                    ans[l] = nums[i];
                    l += 2;
                }
                else if (nums[i] > mid)
                {
                    ans[r] = nums[i];
                    r -= 2;
                }
            }
        }
        for (int i = 0; i < nums.length; i++)
        {
            nums[i] = ans[i];
        }
    }

    public static int partition(int[] nums, int l, int r, int rank)
    {
        int left = l, right = r;
        //将数组分割为左右两个数组,左边的小于nums[left],右边的大于nums[left](数组可能为空)
        int now = nums[left];
        while (left < right)
        {
            while (left < right && nums[right] >= now)
            {
                right--;
            }
            nums[left] = nums[right];
            while (left < right && nums[left] <= now)
            {
                left++;
            }
            nums[right] = nums[left];
        }
        //此时nums[left]为主元,检查主元是否就是中位数
        if (left - l == rank)
        {
            return now;
        }
        //判断要查找的元素所在的分区,并递归查找
        else if (left - l < rank)
        {
            return partition(nums, left + 1, r, rank - (left - l + 1));
        }
        else
        {
            return partition(nums, l, right - 1, rank);
        }
    }
}

Last Update 2016.11.19

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值