最大子串和問題(Maximum Subarray)

來源:互聯網
上載者:User

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

這裡我們需要注意子串和子序列之間的區別。子串是指數組中連續的若干個元素,而子序列只要求各元素的順序與其在數組中一致,而沒有連續的要求。對於一個元素數為n的數組,其含有2^n個子序列和n(n+1)/2個子串。如果使用窮舉法,則至少需要O(n^2)的時間才能得到答案。卡耐基梅隆大學的Jay Kadane的給出了一個線性時間演算法,我們就來看看,如何線上性時間內解決最大子串和問題。

要說明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<=k<j),有array[i...k]的和大於0。此時我們要說明的是,滿足條件的和最大子串,只能是上述某個子串的首碼,而不可能跨越多個子串。我們假設array[p...q],是array的和最大子串,且array[p...q],跨越了array[i...j],array[j+1...k]。根據我們的分組方式,存在i<=m<j使得array[i...m]的和是array[i...j]中的最大值,存在j+1<=n<k使得array[j+1...n]的和是array[j+1...k]的最大值。由於array[m+1...j]使得array[i...j]的和小於0。此時我們可以比較array[i...m]和array[j+1...n],如果array[i...m]的和大於array[j+1...n]則array[i...m]>array[p...q],否array[j+1...n]>array[p...q],無論誰大,我們都可以找到比array[p...q]和更大的子串,這與我們的假設矛盾,所以滿足條件的array[p...q]不可能跨越兩個子串。對於跨越更多子串的情況,由於各子串的和均為負值,所以同樣可以證明存在和更大的非跨越子串的存在。對於單元素和最大的特例,該結論也適用。

根據上述結論,我們就得到了Kadane演算法的執行流程,從頭到尾遍曆目標數組,將數組分割為滿足上述條件的子串,同時得到各子串的最大首碼和,然後比較各子串的最大首碼和,得到最終答案。我們以array={−2, 1, −3, 4, −1, 2, 1, −5, 4}為例,來簡單說明一下演算法步驟。通過遍曆,可以將數組分割為如下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){unsigned int i, cur_left, cur_right;int cur_max, max;cur_max = max = left = right = cur_left = cur_right = 0;for(i = 0; i < length; ++i){cur_max += array[i];if(cur_max > 0){cur_right = i;if(max < cur_max){max = cur_max;left = cur_left;right = cur_right;}}else{cur_max = 0;cur_left = cur_right = i + 1;}}return max;}

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

該問題是1977年Ulf Grenander提出的一個數位影像方面的問題,1984年Jay Kadane才給出了這個優美的解決方案。有些問題,看似解法簡單,但是實際上其原理,要比代碼複雜得多。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.