方法、桶排序
为了满足O(n)复杂度,尝试计数排序,但是会TLE。因此使用桶排序来做
计数排序可以看做是桶大小为1的桶排序,但由于桶数目太多导致遍历时间过长
最大gap肯定是出现在后一个有效桶的min与前一个有效桶的max之间
(“有效”指的是忽略空桶)
步骤思路:
1、数组中有N个元素,最小元素为min、最大元素为max
2、平均间隔为gap = ceil( (max - min) / (N - 1)) ceil指结果向上取整
3、总共分成 bucketCount =ceil((max - min)/ gap ) 个区间(一个区间也就是一个桶),每个区间元素范围是 [ min + k * gap , min + (k + 1) * gap )
4、每个元素对应的桶号(区间)为 bucketNum = (kVal - min)/ gap
桶排序,由于num中的数字肯定在[min,max]区间内
所以根据抽屉原理,假设num中有n个数字,则最大的gap必然要大于dis=(max-min)/(n-1)
所以我们可以把num所在的范围分成等间隔的区间,相邻区间内的元素之间的最大差值,即为要寻找的gap
class MaxDivision {
public:
int findMaxDivision(vector<int> A, int n) {
if (n < 2)
return 0;
// write code here
int max_val = *max_element(A.begin(), A.end());
int min_val = *min_element(A.begin(), A.end());
//平均间距一定要向上取整,只能多不能少,因为少了会导致计算桶号时比实际的偏大以至于超过桶数
int avg_gap = ceil((double)(max_val - min_val) / (n - 1));
//first is the min value of this bunket,second is the max value of this bunket
//桶的数量直接 n - 1 就行了
vector<std::pair<int, int>> bunket(n - 1, make_pair(INT_MAX, INT_MIN));
for (auto num : A) {
if (num == max_val || num == min_val)
continue;
int bunket_num = (num - min_val) / avg_gap;
if (num < bunket[bunket_num].first)
bunket[bunket_num].first = num;
if (num > bunket[bunket_num].second)
bunket[bunket_num].second = num;
}
int maxGap = 0; //return value
int lastMax = min_val;
for (auto val : bunket) {
if (val.first == INT_MAX)
continue;
int tmp = val.first - lastMax;
maxGap = tmp > maxGap ? tmp : maxGap;
lastMax = val.second;
}
int tmp = max_val - lastMax;
maxGap = tmp > maxGap ? tmp : maxGap;
return maxGap;
}
};