007求数组中子数组最大的和

题目描述:
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为O(n)。

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

思路一,暴力法。通过三层循环,找出所有子数组,求和,比较,得出最大和,时间复杂度O(n^3)

int maxsum01(int array[],int n)
{
	int sum = 0;
	int max = 0;
	for(int i=0;imax)
				max = sum;
			sum=0;
		}
	}
	return max;
}
思路二,线性遍历数组,如果将当前元素加入之后sum<=0,说明截至到该元素,往后再加元素也不会达到子数组和最大,此时将sum更换为下一个元素,每次加入新元素之后都会与现有的max进行比较,以保留最大值。时间复杂度O(n)

int maxsum02(int array[],int n)
{
	int sum = 0;
	int max = array[0];

	for(int i=0;i=0)
		{
			sum += array[i];
		}
		else
		{
			sum = array[i];
		}
		if(sum>max)
			max = sum;
	}
	return max;
}

当数组元素全为负数时,返回数组中最大元素值。

思路三,利用动态规划的方法

设sum[i] 为前i个元素中,包含第i个元素且和最大的连续子数组,result 为已找到的子数组中和最大的。对第i+1个元素有两种选择:做为新子数组的第一个元素、放入前面找到的子数组。
sum[i+1] = max(a[i+1], sum[i] + a[i+1])
result = max(result, sum[i])

int maxsum03(int array[],int n)
{
	int sum = array[0];
	int max = array[0];
	for(int i=1;i

问题扩展

  1. 如果数组是二维数组,同样要你求最大子数组的和列?
  2. 如果是要你求子数组的最大乘积列?《???
  3. 如果同时要求输出子段的开始和结束列?
对于第二题,有一个题目可以参考《 给定一个长度为N的整数数组,只允许用乘法,不能用除法,计算任意(N-1)个数的组合乘积中最大的一组》

思路是使用线性扫描,使用空间换时间,用数组b[i]保存a[0]*...*a[i-1]*a[i+1]*...a[n-1]。代码如下:

int makeArray(int a[],int b[],int n)
{
	b[0]=1;
	for(int i=1;i0;j--)
	{
		b[0] *= a[j+1];
		b[j] *= b[0];//b[j]=a[n-1]*...*a[j+1]*a[j-1]*...*a[0]
	}
	b[0] *= a[1];
	int max = -2147483647 - 1;
	cout<

举一反三

1 给定整型数组,其中每个元素表示木板的高度,木板的宽度都相同,求这些木板拼出的最大矩形的面积。并分析时间复杂度。

此题类似leetcode里面关于连通器的题,需要明确的是高度可能为0,长度最长的矩形并不一定是最大矩形,还需要考虑高度很高,但长度较短的矩形。如[5,4,3,2,4,5,0,7,8,4,6]中最大矩形的高度是[7,8,4,6]组成的矩形,面积为16。

解决思路:使用分治递归的方法,即在[start,end]区域计算出矩形的面积,计算左侧的面积,计算右侧的面积,找出三者中面积最大的,返回

//最大值 
 
int MAX(int a,int b) 
{ 
    return a > b ? a : b; 
} 
//给定数组表示单位宽度木板的高,求最大矩形的面积 
int MaxSquare(int*a,int start,int end,int &Max) 
{ 
    if(end < start) 
        return 0; 
    if(end == start) 
        return a[end]; 
 
    int minindex = start; 
    for(int i = start;i <=end;i++)//每次求出区间的最小高度 
        if(a[i] < a[minindex]) 
            minindex = i; 
    int all = a[minindex] * (end - start +1);//以最小高度的最长矩形的面积 
    int lf = MaxSquare(a,start,minindex -1,Max);//左区域的最大面积 
    int rg = MaxSquare(a,minindex +1,end,Max);//右区域的最大面积 
    int t =MAX(all,MAX(lf,rg));//当前区间的最大面积 
    Max = MAX(Max,t); 
    return t; 
} 
 
int MaxSquare(int*a,int n) 
{ 
    int minindex = 0; 
    int max = 0; 
    MaxSquare(a,0,n-1,max); 
    return max; 
} 


2、 最大子矩阵和

一个M*N的矩阵,找到此矩阵的一个子矩阵,并且这个子矩阵的元素的和是最大的,输出这个最大的值。如果所有数都是负数,就输出0。 例如:3*5的矩阵:

1 2 0 3 4

2 3 4 5 1

1 1 5 3 0

和最大的子矩阵是:

4 5

5 3

最后输出和的最大值17。

原题目给出的答案可能有问题,对于子矩阵

3 4 5

1 5 3

的值要比给出的矩阵的和要大

解决思路:在求最大子数组和的基础上,对于矩阵从i到j行,相加,得到一个数组,求出a[i][0-m]到a[j][0-m]之间和最大的子矩阵的和

int maxSubMatrix(int matrix[5][5],const int n,const int m)
{
	int i,j,k,max=0,sum=-10000;
	int b[101];

	for(i=0;i sum)
			{
				sum = max;
			}
		}
		
	}
	return sum;
}


3、 允许交换两个数的位置 求最大子数组和。( ???

// you can also use includes, for example:
#include 

int help(vector &a) {
    int n = a.size();
    vector f,g;
    f.resize(n);
    f[0] = a[0];
    int now = a[0];
    for (int i = 1; i < n; ++i) {
        now = max(now, a[i]);
        f[i] = max(a[i] + f[i - 1], now);
    }
    g.resize(n);
    g[n - 1] = a[n - 1];
    int answer = a[n - 1];
    for (int i = n - 2; i >= 0; --i) {
        g[i] = max(g[i + 1], 0) + a[i];
        answer = max(answer, g[i]);
    }
    for (int i = 1; i < n; ++i) {
        answer = max(answer, g[i] - a[i] + f[i - 1]);
    }
    return answer;
}

int solution(vector &A) {
    // write your code in C++11
    int answer = help(A);
    for (int i = 0, j = A.size() - 1; i < j; ++i,--j) {
        swap(A[i],A[j]);
    }
    answer = max(answer,help(A));
    return answer;
    
}




你可能感兴趣的:(算法知识)