算法設計--在數組中找求和最大的連續子串


問題:輸入具有n個整數的向量arr,輸出向量的任意連續子向量和的最大值

特殊情況(1、當向量都為正數時,為整個向量

     2、當向量都為負數時,為0,即空子串

    )

1、O(n2)的算法 (循環對所有情況進行遍歷)

 1 #include <stdio.h>
 2 #define max(a,b) ((a>b)?a:b)
 3 #define max3(a,b,c) ((a>b)?((a>c)?a:c):((b>c)?b:c))
 4 
 5 int find1(int arr[], int n){
 6     int i,j,sum,maxsofar; 7 maxsofar = 0; 8 9 for(i=0; i<n; i++){ 10 sum = 0; 11 for(j=i; j<n; j++){ 12 sum += arr[j]; 13 maxsofar = max(sum, maxsofar); 14  } 15  } 16 return maxsofar; 17 }

其中有個小細節就是 注意sum(i, j-1) 和 sum(i, j)的關系,不要每次在求和的時候從頭(i的位置)開始,那樣會使復雜度變為O(n3)

 


 

2、O(nlogn)算法

基於分治原理的算法:首先將n的原問題划分為大小基本相等的兩個子問題,我們分別稱為a和b子問題,可以遞歸找出a和b問題的最大子向量,稱為maxa 和 maxb。

但他們兩個之間的最大值不一定使我們求得n問題的最優解,還有一種可能是跨越a和b的邊界,我們稱之為c,c情況的最優解為maxc。

那么問題變成了如何求解maxc?

我們可以發現,maxc中在a的部分為a中包括a的右邊界的最大值,maxc中在b的部分為b中包括b的左邊界的最大值,因此可以在O(N)的時間內算出maxc

因此得到T(N) = 2T(N/2) + O(N)

推導得到T(N) = O(nlogn)

 1 int find2(int arr[], int s_p, int e_p){
 2     int m, sum, i, maxsofar, lmaxsofar, rmaxsofar; 3 maxsofar = 0; 4 5 if(s_p == e_p){ 6 return maxsofar; 7  } 8 else if(s_p == e_p){ 9 return max(arr[s_p],0); 10  } 11 else{ 12 m = (s_p + e_p) / 2; 13 14 lmaxsofar = 0; 15 sum = 0; 16 for(i=m; i>=s_p; i--){ 17 sum += arr[i]; 18 lmaxsofar = max(sum, lmaxsofar); 19  } 20 21 rmaxsofar = 0; 22 sum = 0; 23 for(i=m+1; i<=e_p; i++){ 24 sum += arr[i]; 25 rmaxsofar = max(sum, rmaxsofar); 26  } 27 28 return max3(lmaxsofar+rmaxsofar,find2(arr, s_p, m), find2(arr, m+1, e_p)); 29  } 30 }

3、O(n)算法

先上代碼,代碼非常簡短,理解起來比較困難,但是執行效率非常高

 1 int find3(int arr[], int n){
 2     int i,maxsofar,maxendinghere;
 3     maxsofar = 0;
 4     maxendinghere = 0;
 5     
 6     for(i=0; i<n; i++){
 7         maxendinghere = max(maxendinghere + arr[i], 0);
 8         maxsofar = max(maxsofar, maxendinghere);
 9     }
10 
11     return maxsofar;
12 }

假設我們已經解決了x[0,n-1]的問題,利用分治算法的原理:前i個元素中,最大總和子數組要么在前i-1個元素中,要么其結束位置在i處。

分析其結束為止在i處的情況,那么子向量中除去i處的元素組成的子向量一定是x[0,i-1]中結束位置為i-1的最大子向量。

看代碼中的關鍵變量為maxendinghere:在循環語句的第一個賦值語句之前,maxendinghere是結束位置為i-1的最大子向量的和;賦值語句將其修改為結束位置為i的最大子向量的和。若加上x[i]后結果依然為正值,則結束位置在i的最大子向量值就為maxendinghere+x[i],如果為負值,則重置為0。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM