[LintCode]400.最大间距

本文介绍了一种在O(n)时间内找到未排序数组中排序后连续两要素的最大间距的方法。利用桶排序思想,首先确定数组的最大值和最小值,然后分配到适当数量的桶中,并确保每个桶内包含局部最大值和最小值。最后通过遍历桶来计算最大间距。

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

给定一个未经排序的数组,请找出其排序表中连续两个要素的最大间距。

如果数组中的要素少于 2 个,请返回 0。

 注意事项

可以假定数组中的所有要素都是非负整数,且最大不超过 32 位整数。

样例

给定数组 [1, 9, 2, 5],其排序表为 [1, 2, 5, 9],其最大的间距是在 5 和 9 之间,= 4.

挑战 

用排序的方法解决这个问题是比较简单的方法,但是排序的时间复杂度是O(nlogn), 能否使用线性的时间和空间复杂度的方法解决这个问题。

思路: 先要给数组排序,要求是线性的时间和空间复杂度,只能用桶排序或者基数排序。用桶排序,首先找出数组的最大值和最小值,然后要确定每个桶的容量,再确定桶的个数,然后需要在每个桶中找出局部最大值和最小值,而最大间距的两个数不会在同一个桶中,而是一个桶的最小值和另一个桶的最大值之间的间距。
class Gap {
public:
    int maxGap(vector<int> A, int n) {
        int minValue=INT_MAX,maxValue=INT_MIN;
        for(int i=0;i<n;i++){
            maxValue = max(maxValue, A[i]);
            minValue = min(minValue, A[i]);
        }
        vector<int> bocketMax(n,INT_MIN);
        vector<int> bocketMin(n,INT_MAX);
        int len=maxValue-minValue;
        //桶内不排序,只保留两个数,一个最大值,一个最小值,这两个数不断更新。其他数一概不要。
        for(int i=0;i<n;i++){
        //桶的宽度d = len/ n,桶的个数为(A[i]- min)/d  桶号:((A[i] - min) * n) / len
            int index=(double)(A[i]-minValue)/len*(n-1);//桶号
            bocketMax[index]=max(A[i],bocketMax[index]);
            bocketMin[index]=min(A[i],bocketMin[index]);
        }
        //最大间距的两个数不在同一个桶中,而是后一个桶的最小值减去前一个桶的最大值
        int res=0,pre=bocketMax[0];
        for(int i=1;i<n;i++){
            if(bocketMin[i]!=INT_MAX){
                res=max(res,bocketMin[i]-pre);
                pre=bocketMax[i];//桶号
            }
        }
        return res;
    }
};

上面那种AC不能通过,在网上看到下面这个可以:

class Solution {
public:
    /*
     * @param nums: an array of integers
     * @return: the maximun difference
     */
    int maximumGap(vector<int> nums) {
        if (nums.empty()) return 0;
        int mx = INT_MIN, mn = INT_MAX, n = nums.size();
        for (int i=0;i<n;i++) {
            mx = max(mx, nums[i]);
            mn = min(mn, nums[i]);
        }
        int size = (mx - mn) / n + 1;
        int bucket_nums = (mx - mn) / size + 1;
        vector<int> bucket_min(bucket_nums, INT_MAX);
        vector<int> bucket_max(bucket_nums, INT_MIN);
        set<int> s;
        for (int i=0;i<n;i++) {
            int idx = (nums[i] - mn) / size;
            bucket_min[idx] = min(bucket_min[idx], nums[i]);
            bucket_max[idx] = max(bucket_max[idx], nums[i]);
            s.insert(idx);//在set中插入元素
        }
        int pre = 0, res = 0;
        for (int i = 1; i < n; ++i) {
            if (!s.count(i)) continue;//查找键key的元素个数
            res = max(res, bucket_min[i] - bucket_max[pre]);
            pre = i;
        }
        return res;
    }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值