最大子串和問題(Maximum Subarray)

2021-07-10 07:37:47 字數 1288 閱讀 9098

又乙個經典問題,對於乙個包含負值的數字串array[1...n],要找到他的乙個子串array[i...j](0<=i<=j<=n),使得在array的所有子串中,array[i...j]的和最大。

這裡我們需要注意子串和子串行之間的區別。

子串是指數組中連續的若干個元素。

子串行只要求各元素的順序與其在陣列中一致,而沒有連續的要求。

對於乙個元素數為n的陣列,其含有2^n個子序列和n(n+1)/2個子串。

要說明kadane演算法的正確性,需要兩個結論。

首先,對於array[1...n],如果array[i...j]就是滿足和最大的子串,那麼對於任何k(i<=k<=j),我們有array[i...k]的和大於0。

因為如果存在k使得array[i...k]的和小於0,那麼我們就有array[k+1...j]的和大於array[i...j],這與我們假設的array[i...j]就是array中和最大子串矛盾。

與其次,我們可以將陣列從左到右分割為若干子串,使得除了最後乙個子串之外,其餘子串的各元素之和小於0,

且對於所有子串array[i...j]和任意k(i<=karray[p...q],否array[j+1...n]>array[p...q],無論誰大,我們都可以找到比array[p...q]和更大的子串,這

我們的假設矛盾,所以滿足條件的array[p...q]不可能跨越兩個子串。對於跨越更多子串的情況,由於各子串的和均為負值,所以同樣可以證明存在和更大的非跨越子串的存在。對於單元素和最大的特例,該結論也適用。

根據上述結論,我們就得到了kadane演算法的執行流程,從頭到尾遍歷目標陣列,將陣列分割為滿足上述條件的子串,同時得到各子串的最大字首和,然後比較各子串的最大字首和,得到最終答案。

我們以array=為例,來簡單說明一下演算法步驟。

通過遍歷,可以將陣列分割為如下3個子串(-2),(1,-3),(4,-1,2,1,-5,4),這裡對於(-2)這樣的情況,單獨分為一組。各子串的最大字首和為-2,1,6,所以目標串的最大子串和為6

int kadane(const int array, size_t length, unsigned int& left, unsigned int& right)

}else

}return max;}

這裡我們需要注意,對於陣列元素全為負的情況,由於不滿足上述的兩條結論,所以kadane演算法無法給出正確答案。

該問題是2023年ulf grenander提出的乙個數字影象方面的問題,2023年jay kadane才給出了這個優美的解決方案。有些問題,看似解法簡單,但是實際上其原理,要比**複雜得多。

最大子串和問題

問題 給定一組數字,求連續的字串的最大的和。這裡要注意題目中是子串和而不是子串行和。子串行只要求各元素的順序與其在陣列中一致,而沒有連續的要求。如果求子序列,可直接把這組數字中的正數相加即可。最開始想著只要把這組數字中各個正數子串行分別求和,比較哪個大就行了,後來發現不對。比如 正數子串行分別為,其...

經典問題 最大子串和

最近幾天好好的研究了一下這個問題。問題本身就不多說了,求一串數字中的所有子串中,和最大的乙個子串。例如 輸入 10 5 2 3 4 5 23 3 7 21 輸出 14 5 4 一 各種方法 方法1 maxsofar 0 for i 0 n for j i,n sum 0 for k i,j sum ...

最大子串問題

例如 2,4,7,20,1,1,1,1,10,1,1,1,10,10,10,10,25,10,10,10,10,10,10,300 首先,看到這個問題我們最先想到的一種方法就是 找到所有的子串,然後通過依次比較,找到最大的。接下來我們演示一下這種方法的 public int getmaxvalue ...