从无序序列中求这个序列排序后邻点间最大差值的O(n)算法
标题可能比较绕口,简单点说就是给你一个无序数列A={a1,a2,a3……an},如果你把这个序列排序后变成序列B,求序列B中相邻两个元素之间相差数值的最大值。
注意:序列A的元素的大小在[1,2^31-1]之间
首先,因为要O(n)查找,你不能对序列A进行排序。
不过我们有显而易见的一个结论那就是最大差值,肯定大于平均差值
而序列的平均差值avg=(MAX(ai)-MIN(ai))/n-1
这个结论有啥用呢?
答:可以用来分块,我以avg为块长把n个元素用映射函数f(x)=(x-MIN(a[i]))/avg 映射到n-1个块内。
首先块内的差值的肯定小于平均值,所以就不用算了,所以只要算块间的差值,而块间的差值就是一个块的最大值,减去另一个块的最小值
上述算法都可以O(n)实现,所以总算法复杂度O(n)。(*^▽^*)
代码实现:
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <vector> 5 using namespace std; 6 const int SIZE = 1e6+7; 7 int a[SIZE]; 8 int maxVal[SIZE],minVal[SIZE]; 9 10 int main(){ 11 int n,MIN = 2100000000+7,MAX = -1; 12 scanf("%d",&n); 13 for(int i=0;i<n;++i){ 14 scanf("%d",&a[i]); 15 MIN = min(MIN,a[i]); 16 MAX = max(MAX,a[i]); 17 maxVal[i] = -1; 18 minVal[i] = 2100000000 + 7; 19 } 20 int temp = (MAX-MIN)/(n-1); 21 for(int i=0;i<n;++i){ 22 int id = (a[i] - MIN)/temp; 23 minVal[id] = min(minVal[id],a[i]); 24 maxVal[id] = max(maxVal[id],a[i]); 25 } 26 int ans = (MAX-MIN)/(n-1); 27 MAX = -1,MIN = -1; 28 for(int i=0;i<=n;++i){ 29 if(maxVal[i] == -1) continue; 30 MIN = minVal[i]; 31 if(MAX != -1){ 32 ans = max(ans,MIN-MAX); 33 } 34 MAX = maxVal[i]; 35 } 36 printf("%d\n",ans); 37 return 0; 38 }