問題陳述:
給定N個整數的序列{A1, A2, ... , AN},求函數ƒ(i, j) = max{0, Ai + Ai+1 + ... + Aj}(1<=i<j<=N)的最大值。
問題分析:
求給定數列的最大子列和。
算法設計:
算法1:計算每個子列的和
時間復雜度: T(N) = O(N2)
1 int MaxSubSeqSum(int arr[], int n) { 2 int i, j, currentSum, maxSum = 0; 3 for(i=0; i<N-1; i++) { /* i是子列左端的位置 */ 4 currentSum = 0; /* currentSum是從A[i]到A[j]的子列和 */ 5 for(j=i; j<N; j++) { /* j是子列右端位置 */ 6 currentSum += arr[j]; 7 if(currentSum > maxSum){ 8 maxSum = currentSum; //更新maxSum 9 } 10 } 11 } 12 return maxSum; 13 }
算法2:遞歸 分而治之
將數列分為兩部分,分別求出左右兩側的最大子數列,再求出跨越分界線的最大子數列,比較三者最大值即為所求的最大子數列。
時間復雜度: T(N) = O(NlogN)
1 int MaxSubSeqSum(int arr[], int left, int right) { 2 if(left == right){ 3 if(arr[left] > 0){ 4 return arr[left]; 5 }else { 6 return 0; 7 } 8 } 9 10 int center = (left + right) / 2; 11 int leftMaxSum = MaxSubSeqSum(arr, left, center); /* 分界線左側最大子數列 */ 12 int rigthMaxSum = MaxSubSeqSum(arr, center+1, right); /* 分界線右側最大子數列 */ 13 14 /* 以分界線往左求最大子數列 */ 15 int leftBorderSum = 0, maxLeftBorderSum = 0; 16 for(int i=center; i>=left; i--) { 17 leftBorderSum += arr[i]; 18 if(leftBorderSum > maxLeftBorderSum){ 19 maxLeftBorderSum = leftBorderSum; 20 } 21 } 22 23 /* 以分界線往右求最大子數列 */ 24 int rightBorderSum = 0, maxRightBorderSum = 0; 25 for(int j=center+1; j<=right; j++) { 26 rightBorderSum += arr[j]; 27 if(rightBorderSum > maxRightBorderSum) { 28 maxRightBorderSum = rightBorderSum; 29 } 30 } 31 32 /* 跨越分界線最大子數列和 */ 33 int maxBorderSum = maxLeftBorderSum + maxRightBorderSum; 34 35 return maxSum(leftMaxSum, rigthMaxSum, maxBorderSum); 36 } 37 38 /* 39 ** 返回a, b, c三者最大值 40 */ 41 int maxSum(int a, int b, int c){ 42 if(a > b) { 43 a = b; 44 } 45 if(a > c) { 46 return a; 47 }else { 48 return c; 49 } 50 }
時間復雜度計算:
T(N) = 2 * T(N/2) + cN
= 22 * T(N/22) + c2N
= 2k * T(N/2k) + ckN 其中 N/2k = 1
= N * T(1) + cNlog2N
= O(NlogN)
算法3:在線處理(每輸入一個數據就進行即時處理)
時間復雜度: T(N) = O(N)
1 int MaxSubSeqSum(int arr[], int n) { 2 int currentSum, maxSum; 3 currentSum = maxSum = 0; 4 for(int i=0; i<n; i++) { 5 currentSum += arr[i]; /* 向右累加 */ 6 if(currentSum > maxSum) { /* 發現更大值 更新最大值 */ 7 maxSum = currentSum; 8 }else if(currentSum < 0){ /* 如果當前子列為負 舍棄 置零 */ 9 currentSum = 0; 10 } 11 } 12 return maxSum; 13 }
參考資料:浙江大學數據結構
轉載請注明出處:http://www.cnblogs.com/michaelwong/p/4292936.html