這道題是2016美團面試題:ios
1.給定一個數組arr,數組長度爲len,求知足 0 <= a <= b < len的 arr[b] - arr[a]最大值。面試
你的想法:讓每個數字減去它右邊的數字,並經過比較獲得數對的最大值,時間複雜度(O^2),這應該是面試官不想要的。數組
解法一:分治法(遞歸實現)ide
假設把數組分紅兩個子數組,用左數組最大的減去右數組最小的,最大值有三種狀況:spa
(1)被減數和減數都在第一個子數組中,即第一個子數組中的數對之差的最大值;.net
(2)被減數和減數都在第二個子數組中,即第二個子數組中數對之差的最大值;code
(3)被減數在第一個子數組中,是第一個子數組的最大值;減數在第二個子數組中,是第二個子數組的最小值。blog
(1)、(2)、(3)中,這三個差值的最大者就是整個數組中數對之差的最大值。遞歸
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 // 解法1: 分治法(遞歸實現) 5 int Max_Find(int *s,int *e,int *max,int *min) 6 { 7 if(s >= e) 8 { 9 *max = *min = *s; 10 return -1; 11 } 12 int *mid = s+(e-s)/2; 13 14 int maxleft,minleft; 15 int left = Max_Find(s,mid,&maxleft,&minleft); 16 17 int maxright,minright; 18 int right = Max_Find(mid+1,e,&maxright,&minright); 19 20 int sum = maxleft - minright; 21 22 *max = (maxleft > maxright) ? maxleft:maxright; 23 *min = (minleft < minright) ? minleft:minright; 24 25 int m = (left > right) ? left:right; 26 27 m = (m > sum)?m:sum; 28 29 return m; 30 } 31 int MaxDiff(int array[], unsigned int len) 32 { 33 if(NULL == array || len < 2){ 34 return -1; 35 } 36 int max, min; 37 int MaxDiff_Num = Max_Find(array, array+len-1, &max, &min); 38 printf("maxDiff_Num: %d\n\n", MaxDiff_Num); 39 } 40 41 int main() 42 { 43 int a[2] = {10,5}; 44 MaxDiff(a,2); 45 }
解法二:轉化爲求數字數組最大和問題。get
參考:這裏
使用一個輔助數組arr2,則arr2[i] = arr[i] - arr[i+1]
即:arr2中從i加到j,arr2[i] + arr2[i+1]+.....+arr2[j]
則:(arr[i]-arr[i+1])+(arr[i+1]-arr[i+2])+....(arr[j]-arr[j+1])
轉化爲arr[i]-arr[j+1]
1 #include <iostream> 2 #include <stack> 3 #include <algorithm> 4 #include <stdio.h> 5 #include <string.h> 6 #include <stdlib.h> 7 using namespace std; 8 int max_find(int arr[],int len) 9 { 10 if(arr == NULL || len < 2) 11 { 12 return -1; 13 } 14 int *arr2 = new int[len - 1]; 15 int i = 0; 16 for(i = 0;i < len-1;++i) 17 { 18 arr2[i] = arr[i] - arr[i+1]; 19 } 20 int curS = 0; 21 int max = -1; 22 for(i = 0;i < len-1;++i) 23 { 24 if(curS <= 0) 25 { 26 curS = arr2[i]; 27 }else 28 { 29 curS +=arr2[i]; 30 } 31 if(curS > max) 32 { 33 max = curS; 34 } 35 } 36 if(arr2) 37 { 38 delete [] arr2; 39 arr2 = NULL; 40 } 41 printf("%d",max); 42 } 43 int main() 44 { 45 int a[2] = {10,5}; 46 max_find(a,2); 47 }
解法三:動態規劃法
依次遍歷數組用arr[i-1]以前的最大 值減去右邊的元素
1 #include <iostream> 2 #include <stack> 3 #include <algorithm> 4 #include <stdio.h> 5 #include <string.h> 6 #include <stdlib.h> 7 using namespace std; 8 int max_find(int arr[],int len) 9 { 10 if(arr == NULL || len < 2) 11 { 12 return -1; 13 } 14 int max = arr[0]; 15 int sum = max - arr[1];//初始化數對差 16 int i = 0; 17 for(i = 2;i < len;++i) 18 { 19 if(arr[i-1] > max) 20 { 21 max = arr[i-1]; //左側最大值 22 } 23 int cur = max - arr[i];//用最大的值減右側的最小值 24 if(cur > sum) //判斷是不是最大數對之差 25 { 26 sum = cur; 27 } 28 } 29 printf("%d",sum); 30 } 31 int main() 32 { 33 int a[2] = {10,5}; 34 max_find(a,2); 35 }
以上三種都是O(n),那麼:
第一種:遞歸,有遞歸棧
第二種:要n-1輔助數組
第三種:推薦