從無序序列中求這個序列排序後鄰點間最大差值的O(n)算法
阿新 • • 發佈:2018-04-01
算法 之間 一個 差值 最小 size 復雜度 play 實現
標題可能比較繞口,簡單點說就是給你一個無序數列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 = -1View Code; 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 intid = (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 }
從無序序列中求這個序列排序後鄰點間最大差值的O(n)算法