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

391

被折叠的 条评论
为什么被折叠?



