最大子段和演算法分析

2021-09-08 16:38:26 字數 2030 閱讀 8393

最大子段和問題(maximum interval sum)

一.問題描述

給定長度為n的整數序列,a[1...n], 求[1,n]某個子區間[i , j]使得a[i]+…+a[j]和最大.或者求出最大的這個和.例如(-2,11,-4,13,-5,2)的最大子段和為20,所求子區間為[2,4]。

二.演算法分析

1.窮舉法

1

int start = 0;//

起始位置

2int end = 0; //

結束位置

3int max = 0;4

for(int i = 1; i <= n; ++i)517

}18 }

換一種窮舉思路,對於起點 i,我們遍歷所有長度為1,2,…,n-i+1的子區間和,以求得和最大的乙個.這樣也遍歷了所有的起點的不同長度的子區間,同時,對於相同起點的不同長度的子區間,可以利用前面的計算結果來計算後面的。就像傳遞陣列引數時往往傳的不是起止位置,而是起始位置和長度。

1

int start = 0;//

起始位置

2int end = 0;//

結束位置

3int max = 0;4

for(int i = 1; i <= n; ++i)516

}17 }

2.分治法

求子區間及最大和,從結構上是非常適合分治法的,因為所有子區間[start, end]只可能有以下三種可能性:

1.在[1, n/2]這個區域內

2.在[n/2+1, n]這個區域內

3.起點位於[1,n/2],終點位於[n/2+1,n]內

以上三種情形的最大者,即為所求. 前兩種情形符合子問題遞迴特性,所以遞迴可以求出. 對於第三種情形,則必然包括了n/2和n/2+1兩個位置,這樣就可以利用第二種窮舉的思路分別向左右擴張求出:

1

int maxinterval(int *a, int left, int

right)

217 sum = 0;18

int right_max = 0;19

for(int i = center+1; i <= right; ++i)

2025

int res = left_max+right_max;

26if(res 27 res =leftmaxinterval;

28if(res 29 res =rightmaxinterval;

30return

res;

31 }

3.動態規劃並擴充套件到二維空間

令b[j]表示以位置 j 為終點的所有子區間中和最大的乙個

子問題:如j為終點的最大子區間包含了位置j-1,則以j-1為終點的最大子區間必然包括在其中

如果b[j-1] >0, 那麼顯然b[j] = b[j-1] + a[j],用之前最大的乙個加上a[j]即可,因為a[j]必須包含

如果b[j-1]<=0,那麼b[j] = a[j] ,因為既然最大,前面的負數必然不能使你更大

1 #include2  #include

3int a[101][101],b[101],c[101];4

int subsequencesum(int a,intn)5

30return

maxsum;

31}

32int

main()

3351 ans=subsequencesum(b,n);//

算的是兩列間的和,

52if(temp53 temp=ans;54}

55}56 printf("

%d\n

",temp);57}

58//

while(1);

59return0;

60 }

最大子段和問題分析

問題 給定n個整數 可能為負數 組成的序列a 1 a 2 a 3 a n 求該序列如a i a i 1 a j 的子段和的最大值。當所給的整均為負數時定義子段和為0,依此定義,所求的最優值為 max,1 i j n 例如,當 a1,a2,a3,a4,a4,a6 2,11,4,13,5,2 時,最大子...

演算法設計與分析 最大子段和問題

給定由 n個整數組成的序列 求該序列形如 1 分別用蠻力法 分治法和動態規劃法設計最大子段和問題的演算法 2 比較不同演算法的時間效能 3 給出測試資料,寫出程式文件。實驗2.1最大欄位和問題.cpp 此檔案包含 main 函式。程式執行將在此處開始並結束。include using namespa...

最大子段和

設a 是n個整數的序列,稱為該序列的子串行,其中1 i j n.子串行的元素之和稱為a的子段和.例如,a 2,11,4,13,5,2 那麼它的子段和是 長度為1的子段和 2,11,4,13,5,2 長度為2的子段和 9,7,9,8,7 長度為3的子段和 5,20,4,6 長度為4的子段和 18,15...