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; } }