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.
问题描述:
给定n个实数x1,x2,...,xn,求这n个实数在实轴上相邻2个数之间的最大差值,要求设计线性的时间算法
算法思想:
最直接的方法就是对n个数据进行排序,然后一边扫描即可确定相邻的最大间隙。普通的排序方法不满足线性时间的要求。故采取桶排序的方法:
1. 找到n个数据中最大和最小数据maxx和minx;
2. 用n-2个点等分区间[minx,maxx],即将[minx,maxx]等分为n-1个区间(前闭后开区间),将这些区间看做桶,编号为1,2,...,n-2,n-1,且桶i的上界和桶i+1的下届相同,即每个桶的大小相同;
每个桶的大小为: dblAvrGap=(maxx-minx)/(n-1)
实际上,这些桶的边界就构成了一个等差数列(首项为minx,公差d=dblAvrGap),且人为将minx放入第1个桶,将maxx放入第n-1个桶。
编程实现中,用以下数据结果存放有关桶的数据:
int *count=new int[n]; //实际分到每个桶的数据个数
double *low=new double[n]; //实际分到每个桶的最小数据
double *high=new double[n]; //实际分到每个桶的最大数据
3. 将n个数放入n-1个桶中:
3.1 按如下规则将x[i]分配到某个桶(编号index)中: index=int((x[i]-minx)/dblAvrGap)+1;
若x[i]=minx,则被分到第1个桶中(minx即为桶1的下界);
若x[i]=桶j的下界(也是桶j-1的上界),则被分到桶j中(j>=1);
若x[i]=maxx,则被分到桶n中(max为桶n的下界桶n-1的上界),但没有桶n,解决办法:
可人为将其移入桶n-1中或者再加一个桶,这并不影响求其最大间隙;
3.2 调整分到该桶的最大最小数据;
4. 求最大间隙:
除最大最小数据maxx和minx以外的n-2个数据被放入n-1个桶中,由抽屉原理可知至少有一个桶是空的;
又因每个桶的大小相同,所以最大间隙不会在同一桶中出现;
一定是某个桶的上界(dblHigh)和其后某个桶的下界(dblLow)之间隙,且该两桶之间的桶(即编号在该两桶编号之间的桶)一定是空桶;
即最大间隙在桶i的上界和桶j的下界之间产生(j>=i+1);
下面的代码解决了整数数列最大间隙问题(通过了OJ的测试),来自http://blog.csdn.net/u012162613/article/details/41936569:
class Solution { public: int maximumGap(vector<int> &num) { if (num.size() < 2) return 0; //遍历一遍,找出最大最小值 int maxNum = num[0]; int minNum = num[0]; for (int i : num) { maxNum=max(maxNum,i); minNum=min(minNum,i); } // 每个桶的长度len,向上取整所以加+ int len = (maxNum - minNum) / num.size() + 1; //桶的个数:(maxNum - minNum) / len + 1,每个桶里面存储属于该桶的最大值和最小值即可,注意这里的最大最小值是局部的 vector<vector<int>> buckets((maxNum - minNum) / len + 1); for (int x : num) { int i = (x - minNum) / len; if (buckets[i].empty()) { buckets[i].reserve(2); buckets[i].push_back(x); buckets[i].push_back(x); } else { if (x < buckets[i][0]) buckets[i][0] = x; if (x > buckets[i][1]) buckets[i][1] = x; } } //gap的计算,For each non-empty buckets p, find the next non-empty buckets q, return min( q.min - p.max ) int gap = 0; int prev = 0; for (int i = 1; i < buckets.size(); i++) { if (buckets[i].empty()) continue; gap = max(gap, buckets[i][0] - buckets[prev][1]); prev = i; } return gap; } };
另外的代码如下:
输入:
文件格式:
n
x1 x2 ... xn
输出:maxgap(最大间隙)
index | 0 | 1 | 2 | 3 | 4 |
count | 0 | 2 | 1 | 0 | 2 |
low | 7.5 | 1.5 | 3.1 | 7.5 | 6.3 |
high | 1.5 | 2.3 | 3.1 | 1.5 | 7.5 |
index | 0 | 1 | 2 | 3 | 4 |
count | 0 | 2 | 1 | 0 | 2 |
low | 7.5 | 1.5 | 3.0 | 7.5 | 6.3 |
high | 1.5 | 2.3 | 3.0 | 1.5 | 7.5 |
index | 0 | 1 | 2 | 3 | 4 |
count | 0 | 1 | 1 | 1 | 2 |
low | 7.5 | 1.5 | 3.0 | 4.5 | 6.0 |
high | 1.5 | 1.5 | 3.0 | 4.5 | 7.5 |
index | 0 | 1 | 2 | 3 | 4 |
count | 0 | 3 | 0 | 1 | 1 |
low | 10.0 | 1.5 | 10.0 | 6.3 | 10.0 |
high | 1.5 | 3.1 | 3.0 | 6.3 | 10.0 |
index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
count | 0 | 3 | 2 | 0 | 2 | 0 | 2 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 2 |
low | 25.3 | 1.0 | 3.1 | 25.3 | 6.3 | 25.3 | 10.0 | 11.7 | 25.3 | 25.3 | 18.3 | 19.9 | 21.4 | 25.3 | 24.1 |
high | 1.0 | 2.3 | 3.4 | 1.0 | 6.5 | 1.0 | 10.2 | 11.7 | 1.0 | 1.0 | 18.3 | 19.9 | 21.4 | 1.0 | 25.3 |