数组排序之后相邻数的最大差值

给定一个整型数组arr,目标是找出排序后的数组中相邻两数的最大差值。通过桶排序方法可以在O(n)的时间复杂度和O(n)的空间复杂度下解决此问题。首先将数组划分为N个区间,然后遍历数组,将每个元素放入对应的区间,并记录区间内的最大值和最小值。最后,遍历区间寻找最大差值,注意考虑空桶可能导致的最大差值发生在区间边界的情况。

描述

给定一个整形数组arr,返回排序后相邻两数的最大差值
arr = [9, 3, 1, 10]。如果排序,结果为[1, 3, 9, 10],9和3的差为最大差值,故返回6。
arr = [5, 5, 5, 5]。返回0。
[要求] 时间复杂度为O(n),空间复杂度为O(n)

解题思路:

如果直接对数组进行sort排序在遍历查找其时间复杂度达到O(nlogn);

桶排序

1)可将整个数组分为N个区间,假设arr数组最大值为Max,最小值为Min,则各子区间大小为(Max-Min)/N
2)遍历整个arr数组,将arr[i]放入对应的区间内,记录区间内放入数的最大值和最小值
3)遍历完数组可能出现以下情况:

  • 数组大小均匀分配,则最大差值则为相邻区间放入数的最大差值
  • 否则可能出现空桶及一个区间多个值,此时最大差值可能出现在相邻区间,即右区间最小值减左区间最大值;也可能是空桶的右侧区间最小值-左侧区间最大值。 注意: (因为同一个区间即使有多值,但最大差值不可能大于(Max-Min)/N,而由于空桶的出现空桶左右区间存放的数差值绝对大于(Max-Min)/N,因此最大偏差绝不可能出现在同一区间,但最大偏差不是绝对在空桶的左右侧区间,相邻区间存放数的偏差也可能大于(Max-Min)/N)

代码:

#include<bits/stdc++.h>

using namespace std;
int bucket(double num,double sz,double Max,double Min){
    return (int)((num-Min)*sz/(Max-Min));
}
int main(){
    int N;
    cin>>N;
    vector<int>arr(N,0);
    int Min=INT_MAX,Max=INT_MIN;
    for(int i=0;i<N;++i){
        cin>>arr[i];
        Min=min(Min, arr[i]);
        Max=max(Max, arr[i]);
    }
    if(Max==Min){
        cout<<0<<endl;
    }
    vector<bool>bucketHasNum(N,false);
    vector<int>bucketMax(N,INT_MIN);
    vector<int>bucketMin(N,INT_MAX);
    int Digit=0;
    for(int i=0;i<N;++i){
        Digit=bucket(arr[i],N,Max,Min);
        bucketMax[Digit]=bucketHasNum[Digit]?max(bucketMax[Digit],arr[i]):arr[i];
        bucketMin[Digit]=bucketHasNum[Digit]?min(bucketMin[Digit],arr[i]):arr[i];
        bucketHasNum[Digit]=true;
    }
    int res=0;
    int LastMax=bucketMax[0];
    for(int i = 1 ; i < N; i++) {
        if(bucketHasNum[i]) {
            res = max(res, bucketMin[i] - LastMax);
            LastMax=bucketMax[i];
        } 
    }
    cout<<res<<endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值