question 1:
输入一个 非空 整型数组,数组里的数可能为正,也可能为负。
数组中一个或连续的多个整数组成一个子数组。
求所有子数组的和的最大值。
要求时间复杂度为O(n)。
输入:8
1 -2 3 10 -4 7 2 -5
输出:18
解析:首先我们因该知道 a[ i ]前一个位置的区间最大值影响 a[ i ]位置区间最大。
我们分析数组每一个元素都为必选,对于数组里必选第i个数a[ i ],
所以到必选a[ i ] 的位置时,这时区间最大应该为 ma = max(a[i] , ma + a[i]) 。(若ma <0,我们就舍弃前面区间的元素,而只保留自己才是最大值)
ma为a[ i - 1]时区间最大的值,所以要从前向后递推。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1006;
int a[N];
int main(){
int n;
cin>> n;
for(int i = 0;i<n;i++) scanf("%d",&a[i]);
int ans= a[0];
int ma = a[0];
for(int i = 1;i < n;i++){
ma = max(a[i],ma + a[i]);
ans = max(ans,ma);
}
printf("%d\n",ans);
return 0;
}
question 2:
给定一个包含整数的二维矩阵,子矩形是位于整个阵列内的任何大小为1 * 1或更大的连续子阵列。
矩形的总和是该矩形中所有元素的总和。
在这个问题中,具有最大和的子矩形被称为最大子矩形。
例如,下列数组:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
其最大子矩形为:
9 2
-4 1
-1 8
它拥有最大和15。
我们把现在这道题转化为上面一道题就可以,这道题是二维的,我们把数组宽度固定,就可以转化成了上一道题。
#include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <limits>
int ar[106][106];
using namespace std;
int main(){
int n, m, i, j;
scanf("%d",&n);
for( i=1;i<=n;i++)
for( j=1;j<=n;j++)
{
scanf("%d",&ar[i][j]);
ar[i][j]+= ar[i-1][j];
} //求前缀和
int ans = INT_MIN,res;
for( i = 1;i <= n;i++){
for( j = i;j <= n;j++){
res = 0;
for(int k = 1;k <= n;k++){
int w = ar[j][k] - ar[i-1][k];
res = max(res + w,w);
ans = max(ans,res);
} // j和k代表行和列坐标,而i代表宽度的变化
}
}
printf("%d\n",ans);
return 0;
}