首页 > 代码库 > 最大子数组问题
最大子数组问题
求连续子数组的最大和
求子数组的最大和
题目描述:
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。
例如输入的数组为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;
}
}
----------------------------------我是优美的分割线----------------------------------
本文出自 “DamenMai学习之路” 博客,转载请与作者联系!
最大子数组问题