1.题目描述
HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)
2.算法描述
方法1:暴力求解(不推荐)
暴力求解就是找出数组所有子数组的和,返回子数组和的最大值即可。
方法2:分治法(推荐)
子数组和的最大值要么在左边,要么在右边,要么是跨越中间。而左边找最大子数组和右边找最大子数组和原始问题一样。
其中跨越中间的最大子列和应该是从中间开始分别向左右延申得到的最大子列和。
方法3:在线处理
从左往右扫描数组,用maxSum记录扫描到当前位置的最大子列和,用thisSum记录扫描到当前位置的和(这个和不是从头开始的和)。扫描完成后,maxSum就是最大子列和。(具体见代码)
3.代码描述
3.1.Java代码
//方法1:暴力求解
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
int maxSum = Integer.MIN_VALUE;
for(int i=0; i<array.length;i++){//i为子数组左端
int thisSum = 0;
for(int j=i;j<array.length; j++){//j为子数组右端
thisSum += array[j];
if(thisSum>maxSum)
maxSum = thisSum;
}
}
return maxSum;
}
}
//方法2:分治策略
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
return maxSubSum(array, 0, array.length-1);
}
private int maxSubSum(int[] array, int left, int right){
if(left==right)//如果只有一个元素 它就是子自身的最大子列和
return array[left];
int mid = (left+right)/2;
//递归地从左右分别求解最大子列和
int leftMaxSubSum = maxSubSum(array, left, mid);
int rightMaxSubSum = maxSubSum(array, mid+1, right);
//从mid向左扫描至left,将最大和保存在leftBorderSum中
int leftBorderSum = Integer.MIN_VALUE;
int sum = 0;
for(int i=mid;i>=left;i--){
sum += array[i];
if (sum>leftBorderSum)
leftBorderSum = sum;
}
//从mid+1向右扫描至right,将最大和保存在rightBorderSum中
int rightBorderSum = Integer.MIN_VALUE;
sum = 0;
for(int i=mid+1;i<=right;i++){
sum += array[i];
if (sum>rightBorderSum)
rightBorderSum = sum;
}
//返回左边最大子列和、右边最大子列和、跨越中间的最大子列和三者中最大的一个
return Math.max(leftBorderSum+rightBorderSum, Math.max(leftMaxSubSum, rightMaxSubSum));
}
}
//方法3:在线处理
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
int maxSum = Integer.MIN_VALUE, thisSum = 0;
for(int e: array){
thisSum += e;
if (thisSum > maxSum)
maxSum = thisSum;
else if(thisSum < 0)
//如果加上某元素之后使得thisSum小于0,说明最大子列和不可能包含这个元素,从下个元素重新开始
//而之前的最大子列和已经保存在maxSum中了
thisSum = 0;
}
return maxSum;
}
}
3.2.Python代码
#方法1:暴力求解
# -*- coding:utf-8 -*-
class Solution:
def FindGreatestSumOfSubArray(self, array):
# write code here
maxSum = -2**31
length = len(array)
for i in range(length):
thisSum = 0
for j in range(i, length):
thisSum += array[j]
if thisSum > maxSum:
maxSum = thisSum
return maxSum
#方法2:分治策略
# -*- coding:utf-8 -*-
class Solution:
def FindGreatestSumOfSubArray(self, array):
# write code here
def maxSubSum(arr, l, r):
if l==r:
return arr[l]
m = (l+r)/2
ls = maxSubSum(arr, l, m)
rs = maxSubSum(arr, m+1, r)
lbs = -2**31
s = 0
for i in range(m,l-1, -1):
s += arr[i]
if s>lbs:
lbs = s
rbs = -2**31
s = 0
for i in range(m+1, r+1):
s += arr[i]
if s>rbs:
rbs = s
return max(lbs+rbs, max(ls, rs))
return maxSubSum(array, 0, len(array)-1)
#方法3:在线处理
# -*- coding:utf-8 -*-
class Solution:
def FindGreatestSumOfSubArray(self, array):
# write code here
maxSum = -2**31
thisSum = 0
for n in array:
thisSum += n
if thisSum > maxSum:
maxSum = thisSum
elif thisSum<0:
thisSum = 0
return maxSum