给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值。
如果数组元素个数小于 2,则返回 0。
示例 1:
输入: [3,6,9,1]
输出: 3
解释: 排序后的数组是 [1,3,6,9], 其中相邻元素 (3,6) 和 (6,9) 之间都存在最大差值 3。
示例 2:
输入: [10]
输出: 0
解释: 数组元素个数小于 2,因此返回 0。
说明:
你可以假设数组中所有元素都是非负整数,且数值在 32 位有符号整数范围内。
请尝试在线性时间复杂度和空间复杂度的条件下解决此问题。
解析:
本题的难度在于时间复杂度与空间复杂度的要求,线性复杂度的限制要求我们只能用一次或数次遍历数组的方法解决问题。
这里我们使用桶排序的思想。
构建一个桶的数据结构,其中仅保存两个变量,最大值与最小值,用来记录所属该桶的所有数据中最大与最小的两个值。
我们只需要根据数组的数据构建一定数量的桶,将数组的数据插入桶中,最后对桶进行相互比较即可获得数组元素间的最大间距。
空间复杂度:我们根据数组中的元素来构建一定数量的桶,桶的数量不超过元素的数量,且每个桶仅维护两个变量,故空间复杂度为O(n)
时间复杂度:整个计算过程,遍历了两次数组和一次桶,故时间复杂度为O(n*3) = O(n)
class Solution {
public:
//总共N个数字,其平均间隔为(max-min)/N,将其设置为桶的容量
//而两个数字之间的最大差值必然大于等于平均间隔,故最大间隔不可能存在于同一个桶中的两个数字之间
//必然存在与两个桶之间
//故构建桶的数据结构,其仅仅存储桶中元素的最大值与最小值
struct bucket{
bool isUsed = false;
int max = INT_MIN;
int min = INT_MAX;
};
int maximumGap(vector<int>& nums) {
//如果元素数量小于2,返回0
if(nums.size()<2) return 0;
//第一次遍历寻找最大最小值
int min = INT_MAX;
int max = INT_MIN;
for(int num : nums){
if(min > num){
min = num;
}
if(max < num){
max = num;
}
}
//构造桶
int bucketSize = (max - min) / (nums.size() - 1); //桶的容量
if(bucketSize == 0) bucketSize = 1; //当数字非常密集时,可能出现容量为0的可能,将最小容量设置为1
int bucketNum = (max - min) / bucketSize + 1; //桶的数量
vector<bucket> buckets(bucketNum); //桶
//第二次遍历,将所有数字塞进桶中
for(int num : nums){
int pos = (num - min) / bucketSize;
buckets[pos].isUsed = true;
if(buckets[pos].max < num){
buckets[pos].max = num;
}
if(buckets[pos].min > num){
buckets[pos].min = num;
}
}
//遍历桶,获取两个桶之间最大的差值
int res = 0;
int pre = min;
for(int i=0;i<buckets.size();++i){
if(!buckets[i].isUsed) continue; //空桶忽略不计
//将前一桶最大值与该桶最小值进行比较
if(res < buckets[i].min - pre){
res = buckets[i].min - pre;
}
pre = buckets[i].max;
}
return res;
}
};