LeetCode 324. Wiggle Sort II

思路

首先仿照快速排序找出数组的中位数mid,这里平均复杂度O(n),最坏复杂度O(n^2)。
对数组下标作映射(假设数组长度为6):

0 => 1
1 => 3
2 => 5
3 => 0
4 => 2
5 => 4

则把大于mid的数分配给1,3,5,小于mid的数分给0,2,4,完成
注意:
为了防止有相邻两个数都等于中位数的问题,这里有一个分配的技巧:
1、对于0,2,4,将数组元素小于mid的放在前面,这样中位数只会出现在最后一个
2、对于1,3,5,将数组元素大于mid的放在后面,这样中位数只会出现在第一个
如此,中位数不会相邻:
这里写图片描述

public class Solution {  

    public int vi(int n, int original) {  
        int virtual = (1+ 2 *original)%(n|1);  
        return virtual;  
    }  
    public void wiggleSort(int[] nums) {  
        int len = nums.length;  
        int median = findMedian(nums);  
        int i=0, j=0, k=nums.length-1;  
        while(j<=k) {  
            if(nums[vi(len,j)]>median) {  
                swap(nums, vi(len,i++), vi(len,j++));  
            }else if(nums[vi(len,j)]<median) {  
                swap(nums, vi(len,k--), vi(len,j));  
            }else{  
                j++;  
            }  
        }  
    }  
    public int findMedian(int[] nums) {  
        int len = nums.length;  
        if(len%2 == 0) {  
            return (findK(nums, len/2, 0, len-1) + findK(nums, len/2-1, 0, len-1))/2;  
        }else {  
            return findK(nums, len/2, 0, len-1);  
        }  
    }  
    public int findK(int[] nums, int k, int s, int e) {  
        if(s>=e) return nums[s];  
        int m = partition(nums, s, e);  
        if(m == k) return nums[m];  
        else if(m<k) {  
            return findK(nums, k, m+1, e);  
        }else {  
            return findK(nums, k, s, m-1);  
        }  
    }  
    public int partition(int[] nums, int i, int j) {  
        int pivot = nums[i];  
        int m = i;  
        int n = i+1;  
        while(n<=j) {  
            if(nums[n]<pivot){  
                swap(nums, ++m, n);  
            }  
            n++;  
        }  
        swap(nums, i,m);  
        return m;  
    }  
    public void swap(int[] nums, int a, int b) {  
        int temp = nums[a];  
        nums[a] = nums[b];  
        nums[b] = temp;  
    }  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mitsuhide1992

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值