HZ偶爾會拿些專業問題來忽悠那些非計算機專業的同窗。今天測試組開完會後,他又發話了:在古老的一維模式識別中,經常須要計算連續子向量的最大和,當向量全爲正數的時候,問題很好解決。可是,若是向量中包含負數,是否應該包含某個負數,並指望旁邊的正數會彌補它呢?例如:{6,-3,-2,7,-15,1,2,2},連續子向量的最大和爲8(從第0個開始,到第3個爲止)。給一個數組,返回它的最大連續子序列的和,你會不會被他忽悠住?(子向量的長度至少是1)數組
實際上就是求最大的連續子序列和。測試
咱們維護一個臨時序列和,遍歷數組,計算臨時序列和,若是臨時序列和大於最大值,就更新最大值,當臨時序列和小於0時,也就證實此時的序列沒有增加的空間了,將臨時序列和更新爲0,從新計算後續的序列和,最後返回最大值便可。spa
也能夠使用分治法來求此題。對於一個數組來說,最大的連續子序列和,要麼在中間元素的左邊,要麼在中間元素的右邊,要麼跨過中間元素,根據這點能夠利用分治來求。而跨過中間元素的最大子序列和,它的結果一點是從中間元素向兩側來計算的,咱們能夠從中間元素開始,分別向兩端求解最大的序列和,最後返回兩個子序列和的和,注意中間元素只計算一次。code
C++blog
class Solution { public: int FindGreatestSumOfSubArray(vector<int> array) { if(array.size() == 0) return 0; return helper(array, 0, array.size()-1); } int helper(vector<int>& nums, int left, int right){ if(left == right) return nums[left]; int mid = (left + right) / 2; int maxResult = max(helper(nums, left, mid), helper(nums, mid+1, right)); maxResult = max(maxResult, maxCrossMid(nums, mid, left, right)); return maxResult; } int maxCrossMid(vector<int>& nums, int mid, int left, int right){ int lsum = INT_MIN; int tempSum = 0; for(int i = mid; i >= left; --i){ tempSum += nums[i]; lsum = max(tempSum, lsum); } tempSum = 0; int rsum = INT_MIN; for(int i = mid+1; i <= right; ++i){ tempSum += nums[i]; rsum = max(tempSum, rsum); } return (lsum + rsum); } };
Javaio
public class Solution { public int FindGreatestSumOfSubArray(int[] array) { if(array.length == 0) return 0; int max = array[0]; int tempSum = 0; for(int num:array){ tempSum += num; if(max < tempSum) max = tempSum; if(tempSum < 0) tempSum = 0; } return max; } }