陣列的連續最大子段和

2021-09-23 20:04:34 字數 3879 閱讀 2780

問題描述:輸入是乙個大小為n的整型陣列,要求輸出陣列的任何連續子陣列中的最大值。例如:輸入的陣列為array[10] = ;輸出最大連續子陣列和為array[2...6]:187

演算法1:對所有滿足0<=i<=j<=n的(i,j)整數對進行迭代,對每個整數對,程式都要計算array[i...j]的總和,並檢驗該總和是否大於迄今為止的最大總和。

演算法1的偽**描述如下:

1 maxsofar = 0

2for(i=0;ij)

3for(j=i;jj)

4 tmepsum = 0

5for(k=i;k<=j;++k)

6 tempsum +=array[k]

7 maxsofar = max(maxsofar,tempmax)

這段**簡潔明瞭,便於理解,但是程式執行的速度很慢,時間複雜度為o(n^3)。

演算法2:對於演算法1有乙個明顯的方法可以使其執行起來快得多。使得時間複雜度控制住平方o(n^2)。

第乙個平方演算法注意到,array[i...j]的總和與前面計算出的總和(array[i...j-1])密切相關,利用這一點可以達到演算法2。

演算法2_1的偽**描述如下:

1 maxsofar = 0

2for(i=0;ii)

3 tempsum = 0;4

for(j=i;jj)

5 tempsum +=array[j]

6 maxsofar = max(maxsofar,tempsum)

第二個平方演算法是引入乙個陣列curarray,大小也為n,通過空間來換取時間,通過訪問外迴圈執行之前計算[0...i]各個連續字段總和。curarrary中的第i個元素包含array[0...i]中各個數的累加和,所以x[i...j]中各個數的總和可以通過計算curarray[j] -curarray[i-1]得到.

演算法2_2的偽**描述如下:

1 curarray[-1] = 0

2for(i=0;ii)

3 curarray[i] = curarray[i-1]+x[i]

4 maxsofar = 0

5for(i=0;ii)

6for(j=i;jj)

7 sum = curarray[j]-curarray[i-1

]8 maxsofar = max(maxsofar,sum)

演算法3:可以考慮採用法治演算法。初始問題是要處理大小為n的陣列,所以可以將其劃分為兩個子陣列a和b,然後遞迴的找出a、b中元素總和最大的子陣列分別為maxa、maxb。而最大子陣列要麼在a中,要麼在b中,要麼跨越a和b之間的邊界,我們將跨越邊界的最大子陣列記為maxc。我們通過分治演算法計算處了maxa和maxb,通過某種辦法計算處maxc。然後返回三個中的最大值就是我們所要的最大子陣列和。演算法的時間複雜度為o(nlogn)。如何計算maxc呢?通過觀察發現,maxc在a中的部分是a中包含右邊界的最大子陣列,而maxc在b中的部分是b中包含左邊界的最大子陣列。將這些綜合一起我們得到演算法3:

1

int maxsum3(1

,n)2

演算法4:我們現在採用運算元組的最簡單的演算法:從陣列最左端(元素x[0])開始掃瞄,一直到最右端(元素array[n-1])為止,並記下所遇到的最大總和的子陣列。最大總和開始設為0.假設我們已經解決了array[0...i-1]的問題,那麼如何將其擴充套件為包含x[i]的問題呢?我們用類似於分治演算法的原理:前i個元素中,最大總和子陣列要麼在前i-1個元素中(將其存maxsofar中),要麼其結束位置為i(將其存入maxendinghere中)。不從頭開始計算結束位置為i的最大子陣列,而是利用結束位置為i-1的最大子陣列進行計算。這樣就得到了演算法4:

1 maxsofar = 0

2 maxendinghere = 0

3for(i=0;ii)

4 maxendinghere = max(maxendinghere+array[i],0

)5 maxsofar = max(maxsofar,maxendinghere)

理解這個程式的關鍵在於maxendinghere。在迴圈中第乙個賦值語句之前,maxendinghere是結束位置為i-1的最大子陣列的和,賦值語句將其修改為結束位置為i的最大子陣列的和。若加上array[i]的後的結果為正值,則該賦值語句使maxendinghere增大x[i],若加上x[i]之後結果為負值,該賦值語句將maxendinghere重新設定為0(因為結束位置為i的最大子陣列現在為空)。這個地方有些難度,需要認真思考揣摩。時間複雜度為o(n),線性演算法,效率最高。

下面針對這4個演算法寫乙個完成的程式來進行測試,程式如下:

1 。#include 2

using

namespace std; //

求兩個數種最大值

3int max(const

int m,const

intn)

4 //

求三個整數中的最大值

7int max(const

int x,const

int y,const

intz)

8 //

演算法1函式實現

13int maxsum1(int *array,const

size_t len)

1426}27

return

maxsofar;

28 } //

演算法2.1的實現

29int maxsum2_1(int *array,const

size_t len)

3041}42

return

maxsofar;

43 } //

演算法2.2的實現

44int maxsum2_2(int *array,const

size_t len)

45 //

演算法3的實現

59int maxsum3(int *array,const

int begin,const

intend)

6072 tempsum = 0;73

for(int j=mid+1;j<=end;++j)

7478

return max(lmax+rmax,maxsum3(array,begin,mid),maxsum3(array,mid+1

,end));

79 } //

演算法4的實現

80int maxsum4(int *array,const

size_t len)

8189

return

maxsofar;

90 } int

main()91;

93int

choise;

94 cout<

1.演算法1

"<

95 cout<

2.演算法2_1

"<

96 cout<

1.演算法1

"<

97 cout<

3.演算法3

"<

98 cout<

4.演算法4

"<

99 cout<

5.演算法2_2

"<

100 cout<

0.退出

"<

101while(1

)102

126}

127return0;

128 }

參考文獻:《程式設計珠璣》第二版 第八章 演算法設計的藝術

陣列的連續最大子段和

轉至 anker s blog 問題描述 輸入是乙個大小為n的整型陣列,要求輸出陣列的任何連續子陣列中的最大值。例如 輸入的陣列為array 10 輸出最大連續子陣列和為array 2.6 187 演算法1 對所有滿足0 i j n的 i,j 整數對進行迭代,對每個整數對,程式都要計算array i...

陣列的連續最大子段和

最大子段和問題描述 給定由 n 個整數 可能為負整數 組成的序列a1,a2,a3.an,求該數列中連續子段和最大!例如 當 a1,a2,a3,a4,a5 2,11,4,13,5,2 時,最大欄位和為 20 11 4 13 以下例子都是以int data 6 int n 6 演算法一 對所有滿足0 i...

陣列的連續最大子段和

問題描述 輸入是乙個大小為n的整型陣列,要求輸出陣列的任何連續子陣列中的最大值。例如 輸入的陣列為array 10 輸出最大連續子陣列和為array 2.6 187 演算法1 對所有滿足0 i j n的 i,j 整數對進行迭代,對每個整數對,程式都要計算array i.j 的總和,並檢驗該總和是否大...