給定一個整數數組 nums ,找到一個具備最大和的連續子數組(子數組最少包含一個元素),返回其最大和。java
示例:數組
輸入: [-2,1,-3,4,-1,2,1,-5,4], 輸出: 6 解釋: 連續子數組 [4,-1,2,1] 的和最大,爲 6。spa
進階: 若是你已經實現複雜度爲 O(n) 的解法,嘗試使用更爲精妙的分治法求解。code
題解:it
解法一:動態規劃
首先讀完題目咱們知道數組最少是一個元素,那麼此時它的最大和就是這個元素,無論它是正負整數仍是零.那麼當變成兩個元素的時候呢,咱們分析一下:
1.若是第二個元素是正整數,那必定會讓最大和變大
2.若是第二個元素是零的話,對最大和其實沒有影響
3.若是第二個元素是負數的話,那麼最大和就是第一個元素和第二個元素中最大的那個負數,
令dp[i]是數組nums的最大和,推廣到i個數的話
1.若是dp[i - 1]是正數或或者0就加上去
2.若是dp[i -1]是負數的話,就不加入,選第nums[i]爲最大和
而後咱們根據這個條件列出狀態轉移方程,這裏把零放入到第一種狀況中,令dp[i]是數組nums的最大和io
在根據這個狀態轉移方程寫出代碼function
public static int maxSubArray(int[] nums) {
int[] dp = new int[nums.length];
dp[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
if (dp[i - 1] < 0) {
dp[i] = nums[i];
} else {
dp[i] = dp[i - 1] + nums[i];
}
}
int max = dp[0];
for (int i = 1; i < nums.length; i++) {
max = Math.max(max, dp[i]);
}
return max;
}
複製代碼
解法二:分治法 其實感受分治法不如動態規劃來的清晰,可是題目中說進階能夠使用分治法,參考了網上的資料才理解.
咱們來想一想.若是一個數組中的最大子序和拆成兩個部分
1.最大和在左邊
2.最大和在右邊
3.最大和處於中間,跨越左右兩邊,此時最大和是左邊數組的後邊部分和右邊數組的左邊部分合起來的值 因此經過子數組來計算出最大值,咱們須要知道左數組最大值,右數組最大值,局部的最大值,總和,而後根據這些值,比較出全局的最大和.class
public int maxSubArray(int[] nums) {
return mergeCount(nums,0,nums.length)[2];
}
/** * @return 片斷處理後的數組,依次爲:左數組最大值,右數組最大值,局部最大值,總和 * */
public int[] mergeCount(int[] nums,int fromIndex,int toIndex){
int[] result=new int[4];
if(toIndex-fromIndex!=1){
int midIndex=(toIndex+fromIndex)>>>1;
int[] resL=mergeCount(nums,fromIndex,midIndex);
int[] resR=mergeCount(nums,midIndex,toIndex);
result[0]=Math.max(resL[0],resL[3]+resR[0]);
result[1]=Math.max(resR[1],resL[1]+resR[3]);
result[2]=Math.max(Math.max(resL[2],resR[2]),resL[1]+resR[0]);
result[3]=resL[3]+resR[3];
return result;
}
Arrays.fill(result,nums[fromIndex]);
return result;
}
複製代碼