Given an unsorted array, find the maximum difference between the successive elements in its sorted form.
Try to solve it in linear time/space.
Return 0 if the array contains less than 2 elements.
You may assume all elements in the array are non-negative integers and fit in the 32-bit signed integer range.
题目大意:在一个无序的数组中,求这个数组排序完以后,相邻的两个数最大差值,要求保证O(n)的复杂度。
思路: 本题目仅需要2步:
1)排序数组
2)求排序后的数组中相邻元素差值的最大值。
难点:对步骤1),怎么在线性时间/空间中对数组排序。
求解算法:
桶排序:
算出相邻两个桶之间的最大差值;
如果是平均分布,则桶的数目和元素的数目相同时,排序时间的复杂度是O(n);
假设桶的个数和元素的数目相同,若是平均分布,则每个桶有一个数,而若某个桶里有两个以上的元素时,此时必有至少一个桶是空桶,那么最大间隔有可能落在空桶的相邻的两个桶存储的数之间,最大间隔不会落在同一个桶的数里,因此我们不需要对每一个桶再排一次序,只需要记录同一个桶的最大着和最小值,算出前一个有最大值的桶和后一个有最小值的桶之差,该值可能是最大间隔。
步骤:
1)算好用的桶的个数,用最大元素和最小元素算出平均间隔,记录在平均间隔上的最大值和最小值;
2)算出前一个间隔里的最大值和后一个间隔里的最小值之差,取最大的一个。
代码实现:
class Solution {
public:
int maximumGap(vector<int>& nums) {
int n = nums.size();
if (n < 2) return 0;
//1. 算出用的桶数:取平均间隔,再用最大值和最小值之差除以间隔,得到桶数
// 因为假设所有值都是平均分布的时候,如此取桶数可得时间复杂度是0(n)
auto lu = minmax_element(nums.begin(), nums.end());
int l = *lu.first, u = *lu.second;
int agGap = max((u - l) / (n - 1), 1); //平均间隔
int bucketCount = (u - l) / agGap + 1;
//2. 记录每个桶的最大值和最小值
vector<int> bucketsMin(bucketCount, INT_MAX);
vector<int> bucketsMax(bucketCount, INT_MIN);
for (int num : nums) {
int k = (num - l) / agGap;
if (num < bucketsMin[k]) bucketsMin[k] = num;
if (num > bucketsMax[k]) bucketsMax[k] = num;
}
//3. 算出最大间隔
int i = 0, j;
int result = bucketsMax[0] - bucketsMin[0];
while (i < bucketCount) {
j = i + 1;
//忽略空桶
while (j < bucketCount && bucketsMin[j] == INT_MAX && bucketsMax[j] == INT_MIN)
j++;
if (j == bucketCount) break;
result = max(result, bucketsMin[j] - bucketsMax[i]);
i = j;
}
return result;
}
};