1. 程式人生 > >Maximum Subarray連續子序列最大和 -- LeetCode(經典動態規劃)

Maximum Subarray連續子序列最大和 -- LeetCode(經典動態規劃)

原題連結: http://oj.leetcode.com/problems/maximum-subarray/
這是一道非常經典的動態規劃的題目,用到的思路我們在別的動態規劃題目中也很常用,以後我們稱為”區域性最優和全域性最優解法“。
基本思路是這樣的,在每一步,我們維護兩個變數,一個是全域性最優,就是到當前元素為止最優的解是,一個是區域性最優,就是必須包含當前元素的最優的解。接下來說說動態規劃的遞推式(這是動態規劃最重要的步驟,遞迴式出來了,基本上程式碼框架也就出來了)。假設我們已知第i步的global[i](全域性最優)和local[i](區域性最優),那麼第i+1步的表示式是:
local[i+1]=Math.max(A[i], local[i]+A[i]),就是區域性最優是一定要包含當前元素,所以不然就是上一步的區域性最優local[i]+當前元素A[i](因為local[i]一定包含第i個元素,所以不違反條件),但是如果local[i]是負的,那麼加上他就不如不需要的,所以不然就是直接用A[i];

global[i+1]=Math(local[i+1],global[i]),有了當前一步的區域性最優,那麼全域性最優就是當前的區域性最優或者還是原來的全域性最優(所有情況都會被涵蓋進來,因為最優的解如果不包含當前元素,那麼前面會被維護在全域性最優裡面,如果包含當前元素,那麼就是這個區域性最優)。

接下來我們分析一下複雜度,時間上只需要掃描一次陣列,所以時間複雜度是O(n)。空間上我們可以看出表示式中只需要用到上一步local[i]和global[i]就可以得到下一步的結果,所以我們在實現中可以用一個變數來迭代這個結果,不需要是一個數組,也就是如程式中實現的那樣,所以空間複雜度是兩個變數(local和global),即O(2)=O(1)。

程式碼如下: 
  1. publicint maxSubArray(int[] A) {  
  2.     if(A==null || A.length==0)  
  3.         return0;  
  4.     int global = A[0];  
  5.     int local = A[0];  
  6.     for(int i=1;i<A.length;i++)  
  7.     {  
  8.         local = Math.max(A[i],local+A[i]);  
  9.         global = Math.max(local,global);  
  10.     }  
  11.     return global;  
  12. }  
這道題雖然比較簡單,但是用到的動態規劃方法非常的典型,我們在以後的題目中還會遇到,大家還是要深入理解一下哈。我現在記得的用到的題目是Jump Game,以後有統計一下再繼續更新。