从无序序列中求这个序列排序后邻点间最大差值的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 }
View Code

 

posted @ 2018-04-01 17:14  强势围观  阅读(616)  评论(0编辑  收藏  举报