求序列的最大子串行

2021-06-03 02:01:48 字數 2243 閱讀 2521

看《程式設計珠璣》一書,講解求序列的最大子串行。

問題: 給定乙個實數序列x1,x2,…,xn(不必是正數),尋找乙個連續的子串行xi,x(i+1),…,xj,使得其數值之和在所有連續子串行數值之和中是最大的。

演算法1思路:比較所有連續序列數值的和,找到最大的。

1. maxsofar=0;

2. for i=[0,n)

3.   sum=0;

4.   for j=[i,n)

5.      sum=sum+x[j];  

6.      maxsofar=max(sum,maxsofar);

演算法複雜度是o(n2)。

演算法2思路:在演算法1的基礎上改進。演算法1中,第5行要重複求和。用乙個陣列預先存放從陣列第乙個元素開始到各個元素之間所有元素的和。比如定義陣列 a[n+1],

a[0]=0,a[i]=x0+x1+…+x(i-1),(1=a[0]=0;

for i=[1..n]

a[i]=a[i-1]+x[i-1];

maxsofar=0;

for i=[0,n)

sum=0;

for j=[i,n)

sum=a[j+1]-a[i];

maxsofar=max(sum,maxsofar).

演算法複雜度是o(n2)。

演算法3思路:運用歸納法的思想。如果已知x[0…i-1]的最大子串行,那麼能知道x[0…i]的最大子串行嗎?所有不包含x[i]的子串行最大的就是x[0…i-1]的最大子串行,假設為s(i-1),因此,找到包含x[i]的子串行的最大子串行,然後用這個子串行和s(i-1)比較得到x[0..i]的最大子串行。

剛開始我寫出來的演算法:

a[0]=0;

for i=[1..n]

a[i]=a[i-1]+x[i-1];

maxsofar=0;

for i=[0…n)

sum=0;

for j=[0..i-1)

sum=max(sum,a[i+1]-a[j])

maxsofar=max(maxsofar,sum);

演算法複雜度o(n2)。

其演算法複雜度跟上面的一樣。似乎沒有改進。問題出在計算包含xi的最大子串行。我開始簡單看過程式,這個計算過程沒有這麼複雜。我在想是不是也用歸納法試試求這個最大子串行。

如果 x0,x1,…x(i-1)已經知道了包含x(i-1)的最大子串行s(i-1),那麼如何能求x0,x1,…,xi,包含xi的最大子串行?包含xi的乙個子串行=包含x(i-1)的子串行+xi,其中變化的是「包含x(i-1)的子串行」,不變的是xi,因此max(包含xi的乙個子串行)=max(包含x(i-1)的子串行)+xi,當然如果max(包含x(i-1)的子串行)+xi < 0,則max(包含xi的乙個子串行)=0,所以,

max(包含xi的乙個子串行)=max(max(包含x(i-1)的子串行)+xi,0)。

這樣程式就變更新為:

maxsofar=0;

maxtoend=0;

for i=[0…n)

maxtoend=max(maxtoend+x[i],0);

maxsofar=max(maxsofar,maxtoend);

演算法複雜度是o(n)。

求最大子串行演算法的歷史:

布朗大學的uif grenander所面對的模式匹配問題中:最初的問題所描述的是二維陣列。因為二維問題要求的時間太多以至於不能解決,所以grenander將它簡化為一維以對其結構有更好的了解。開始grenander提出了o(n3)的演算法(參加《程式設計珠璣》第8章),後來提出了o(n2)的演算法。

他於2023年將該問題描述給michael shamos,這個傢伙花乙個通宵設計了分治的演算法。不久以後,當shamos向bentley介紹這個問題時,他們一致認為那也許是可能的演算法中最快的。

shamos出息carnegie mellon研討會,在該會議上向統計學家jay kadane描述了該問題以及相關歷史,jay kadeane不出幾分鐘就給出了歸納演算法的提綱。

現在我們看到歸納演算法很簡單,雖然jay kadane很快發現了這個問題,但是當時ulf grenander,michael shamos以及bentley三個聰明的人也沒有「顯而易見」地發現這個演算法。由此可見乙個方法的發現並非是那麼容易的。我們在解決問題時,同樣也並非輕而易舉的就能發現問題的解決方法。當我們沒有解決乙個問題時,完全不需要失望、沮喪,那是我們可能沒有具備相關的知識、背景,靈活運用知識的能力不是突出等等客觀原因所致。要看到我們必然能解決很多的其它問題,保持對自己的信任、保持學習的熱情,這樣自己的能力必然會有增強。

求最大子串行

1.暴力求解,時間複雜度為n 3 int maxsubarray int a int n return maxsum 2.分治法 將陣列從中間分開,那麼最大子陣列要麼完全再左半邊陣列,要麼完全在右半邊陣列,要麼跨立在分界點上。完全在左陣列 右陣列遞迴解決。跨立在分界點上 實際上是左陣列的最大字尾和右...

求最大子串行和

include using namespace std int maxseqsum const int a,int n o n 2 return s2 int maxseqsum2 const int a,int n o n else if s1 0 return s2 int maxseqsum3...

求最大子串行之和

摘要 給出乙個序列,求出其中連續的子串行中和最大的乙個。如 1 3 5 2 1 4 5 最大子串行之和是2 1 4 5 基本思路 最簡單的辦法就是遍歷一邊序列,用變數thissum記錄遍歷過的元素之和,當thisum 0時,繼續相加.若thisum 0,令thisum 0,吧下乙個元素作為新的子串行...