《桶排序》164. 最大间距《leetcode》

164. 最大间距

难度困难293

给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值。

如果数组元素个数小于 2,则返回 0。

示例 1:

输入: [3,6,9,1]
输出: 3
解释: 排序后的数组是 [1,3,6,9], 其中相邻元素 (3,6) 和 (6,9) 之间都存在最大差值 3。

示例 2:

输入: [10]
输出: 0
解释: 数组元素个数小于 2,因此返回 0。

说明:

  • 你可以假设数组中所有元素都是非负整数,且数值在 32 位有符号整数范围内。
  • 请尝试在线性时间复杂度和空间复杂度的条件下解决此问题。

思路解析:

年轻人不讲武德版:

sort O(nlogn) 算一下就好, 啪,很快哦,sort一下直接AC。

因为题目是int 所以 (logN)max=32。  也就是O(32n)其实也不大。

年轻人讲武德版:

O(N) 桶排序。

思路解析:

对于 样例:1 3  9 6  maxVal=9 minVal=1;  

首先就是计算间距,显然,当所有数有序且平均时,数组最大间距的最小值最小。 即桶间间距一定大于桶内间距。(不妨找个例子试试)

dis=(maxVal-minVal)/(n-1)  向上取整。即dis=(9-1)/ 3 向上取整 =3。

//提一点  dis=0  return 0  想一想为什么?   

其次,根据间距计算桶的数量:

bucketNum=(maxVal-minVal)/dis+1;//不+1的话,可能有些元素会被舍弃,

即bucketNum=8/3+1=3; //这里如果选择2的话,9就会被舍弃。

再者对桶进行更新,保存最大值和最小值。

[1,2,3] [4,5,6][7,8,9] 桶的数据范围

更新之后:

[1,3][6,6][9,9] //最小值最大值

最后,找出桶间间距最大的值即可。

空桶的话不更新。

年轻人不讲武德版AC代码:

class Solution {
    public int maximumGap(int[] nums) {
        if(nums.length<2)
            return 0;
        
        Arrays.sort(nums);
        int ans=-1;
        for(int i=1;i<nums.length;i++)
            ans=Math.max(ans,nums[i]-nums[i-1]);
        return ans;
    }
}

年轻人讲武德版AC代码:

class Solution {
    public int maximumGap(int[] nums) {
        int n = nums.length;
        if (n < 2) 
            return 0;
        int minVal=Integer.MAX_VALUE;
        int maxVal=Integer.MIN_VALUE;
        for(int i=0;i<n;i++)
        {
            minVal=Math.min(minVal,nums[i]);
            maxVal=Math.max(maxVal,nums[i]);
        }

        int temp=(maxVal-minVal)/(n-1);
        int dis=(maxVal-minVal)>temp*(n-1)? temp+1 : temp;//n个数有n-1个间隔。 dis为最小的最大间距
        if(dis==0)//所有的值相同。
            return 0;
        int bucketNum=(maxVal-minVal)/dis+1;//不+1的话,可能有些元素会被舍弃, 
        
        int [][] bucket =new int [bucketNum][2];
        for(int i=0;i<bucketNum;i++)//初始化
            Arrays.fill(bucket[i],-1);
        
        for(int i=0;i<n;i++)
        {
            int bucketId=(nums[i]-minVal)/dis;
            if(bucket[bucketId][0]==-1)
            {   
                bucket[bucketId][0]=nums[i];
                bucket[bucketId][1]=nums[i];
            }
            else
            {
                bucket[bucketId][0]=Math.min(bucket[bucketId][0],nums[i]);
                bucket[bucketId][1]=Math.max(bucket[bucketId][1],nums[i]);
            }
        }

        //进一步讲,我们需要考虑有空桶的情况。
        int ans=-1;
        int i=0;
        while(bucket[i][0]==-1)//找到第一个非空桶
            i++;
        int pre=i;

        for(i=pre+1;i<bucketNum;i++)
        {
            if(bucket[i][0]==-1)
                continue;
            ans=Math.max(ans,bucket[i][0]-bucket[pre][1]);//桶间间距,后一个桶的最小值减去前一个桶的最大值。
            pre=i;
        }

        return ans;
    }
}

再提一点:

桶排序,基数排序,计数排序可以再看看

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值