求连续子数组的最大和

求子数组的最大和
题目描述:
输入一个×××数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。

例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,
因此输出为该子数组的和18。

----------------------------------我是优美的分割线----------------------------------

动态规划 复杂度为O(n)

    设test[i]为以第i个元素结尾且和最大的连续子数组。假设对于元素i,所有以它前面的元素结尾的子数组的长度都已经求得,那么以第i个元素结尾且和最大的连续子数组实际上,要么是以第i-1个元素结尾且和最大的连续子数组加上这个元素,要么是只包含第i个元素,即max[i] = max(max[i-1] + test[i], test[i])。可以通过判断max[i-1] + a[i]是否大于a[i]来做选择,而这实际上等价于判断max[i-1]是否大于0。由于每次运算只需要前一次的结果,因此并不需要像普通的动态规划那样保留之前所有的计算结果,只需要保留上一次的即可,因此算法的时间和空间复杂度都很小。

public static int dongtai(){

/**

* 初始化参数

*  leftSum:以test[i-1]为尾的最大子数组值;

*  max:保存遍历时候获得的最大子数组值;

*/

int  leftSum = 0, max=0;

for (int i = 0; i < test.length; i++) {

leftSum = leftSum + test[i] > test[i] ? leftSum + test[i] : test[i];

max = leftSum > max ? leftSum :max ;

}

return max;

}



----------------------------------我是优美的分割线----------------------------------

分治方法 复杂度为O(nlgn)

public class 最大子数组问题 {


public static int[] test = {1, -2, 3, 10, -4, 7, 2, -5};

public static void main(String[] args) {

最大子数组问题 demo = new 最大子数组问题();

System.out.println(demo.MaxSubSum(0,test.length-1));

}


public static int MaxSubSum(int left,int right){

/**

 * 初始化参数

 *  maxLeft:左边最大子串值,maxRight:右边最大子串值;

 *  maxCenterToLeft:从中间往左加最大值,maxCenterToRight:从中间往右加最大值;

 *  maxCenterToLeftSum:从中间往左加的和,maxCenterToRightSum:从中间往右加的和;

 */

int maxLeft=0,maxRight=0;

int maxCenterToLeft=0,maxCenterToRight=0;

int CenterToLeftSum=0,CenterToRightSum=0;

int center=(left + right) / 2;//中间点

//边界

if(left == right){

return test[left];

}

//获得 左边最大子串值 和 右边最大子串值;

maxLeft = MaxSubSum(left,center);

maxRight= MaxSubSum(center+1,right);

//从中间往左加最大值

for (int i = center; i >= left; i--) {

if(maxCenterToLeft < CenterToLeftSum +test[i]){

maxCenterToLeft = CenterToLeftSum +test[i] ;

}

CenterToLeftSum += test[i];

}

//从中间往右加最大值

for (int j = center+1; j < right; j++) {

if(maxCenterToRight < CenterToRightSum +test[j]){

maxCenterToRight =  CenterToRightSum +test[j] ;

}

CenterToRightSum += test[j];

}

//左最大 ,右最大 ,跨中最大 比较 取最大值

int max1 = maxLeft>maxRight ? maxLeft:maxRight;

int max2 = max1>maxCenterToLeft+maxCenterToRight ? max1:maxCenterToLeft+maxCenterToRight;

return max1>max2 ? max1:max2;

}

}

----------------------------------我是优美的分割线----------------------------------