问题描述:
给定n个实数x1,x2,...,xn,求这n个实数在实轴上相邻2个数之间的最大差值,要求
设计线性的时间算法
。
解:
如果不考虑题目的限制条件,那么这道题目不难,很容易想到将这n个实数进行排序,然后遍历,那么所用时间为
Z = T(N) + G(N) 其中,T(N) 为对那个实数进行排序所需要的时间,G(N)为遍历n个实数的时间 。
目前我们所知道的最优的排序效率是 nlogn的。所以这条路走不通。
我的想法:将这n个实数都下取整,那么这n个实数都会落到实数轴上整数点上,有可能发生的情况是
1.多个实数下取整后对应实数轴上的一个整数点,我们只保存这个点处的最大最小值,其他中间值不做记录。(
最大间隙一定不会在这些数中
)
2.某些整数点处只有一个对应的下取整后的实数。
3.某些整数点处没有对应的下取整后的实数。
(1)找到n个实数中的最小值和最大值,下取整,min max;
(2)float low[max - min +1] high[max - min +1] 若有多个实数对应,用于记录对应整数点处最小最大值;float buckets[max - min +1]用于记 录只 有一个实数对应是的实际实数值。bool flag[max -min +1] 用于标记是只有一个对应还是多个,为之后遍历提供方便。
vector<int> stable 用于记录出现过一个以上元素对应的桶序号。
(3)遍历n个实数,将这些点下取整后放入这些桶中。
(4)这次是遍历有一个以上元素对应的桶,找到最大间隙。
例如
如下9个实数:
-4.1 -4.2 -2.3 0.5 1.2 2.3 2.7 5.6 5.9
以上分析虽然可以做到时间复杂度线性增长,有一个问题就是空间复杂度可能很高,比如说一组实数的最大最小值之间相差很大很大的时候。
另外一种算法(王晓东书上讲过的):用
鸽巢原理。
除了max 和 min 外的n-2个数被置于n-1个桶中,由鸽巢原理即知,至少有一个桶是空的,这意味着最大间隙不会出现在同一个同种的两个数之间,对每一个桶做一次线性扫描即可找到最大间隙。