53. 最大子序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1]
输出:1
示例 3:
输入:nums = [0]
输出:0
示例 4:
输入:nums = [-1]
输出:-1
示例 5:
输入:nums = [-100000]
输出:-100000
可以使用动态规划 dp[i]=max( dp[i-1] + nums[i] , nums[i] ),dp[i]只与dp[i-1]和nums[i]有关,因此可以使用一个变量来记录最终的结果,当遍历到的数字大于0,那么可以更新,反之,dp=0;
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int res = INT32_MIN;
int dp=0;
for(int i=0;i<nums.size();i++)
{
dp+=nums[i];
if(dp>res) res=dp;
if(dp<=0) dp=0;
}
return res;
}
};
记录起始位置和终止位置代码如下:
class Solution {
public:
vector<int> maxSubArray(vector<int>& nums) {
int res = INT32_MIN;
int dp=0;
int begin=0,start=0,end=0;
for(int i=0;i<nums.size();i++)
{
dp+=nums[i];
if(dp>res)
{
res=dp;
start=begin;
end=i;
}
if(dp<=0)
{
dp=0;
begin=i+1;
}
}
return {start,end};
}
};
面试题 17.24. 最大子矩阵
给定一个正整数、负整数和 0 组成的 N × M 矩阵,编写代码找出元素总和最大的子矩阵。返回一个数组 [r1, c1, r2, c2],其中 r1, c1 分别代表子矩阵左上角的行号和列号,r2, c2 分别代表右下角的行号和列号。若有多个满足条件的子矩阵,返回任意一个均可。
示例:
输入:
[
[-1,0],
[0,-1]
]
输出:[0,1,0,1]
解释:输入中标粗的元素即为输出所表示的矩阵
说明:1 <= matrix.length, matrix[0].length <= 200
类似于上一题,只不过该题目是二维数组,如下图所示,第一行全部是0,可以看到dp[3]-dp[1] 求解的是前三行的情况记为 col 数组,也就是每一列的前缀和,比如 0+9-4=5,-2+2+1=3,然后遍历该 col 数组,求和的时候为[5,8,0,3] 以数字8为例,可以看做是矩阵[[0,-2],[9,2],[-4,1]] 求和得到8。这样就计算出来子矩阵的大小。
首先遍历每一行,然后对每一列求前缀和,然后运用上一题的基本思路在更改最大值的时候记录坐标。
class Solution {
public:
vector<int> getMaxMatrix(vector<vector<int>>& matrix) {
int m=matrix.size(), n=matrix[0].size();
int maxMat=INT_MIN;
int ri,ci,rj,cj;
for(int r1=0;r1<m;r1++)//遍历起始行
{
vector<int> nums(n);
for(int r2=r1;r2<m;r2++)//遍历结束行
{
int dp=0, start=-1;
for(int i=0;i<n;i++)
{
nums[i]+=matrix[r2][i];//计算每一列的前缀和
if(dp>0) dp+=nums[i];//计算一个矩阵的和
else
{
dp=nums[i];
start=i;
}
if(dp>maxMat)
{
maxMat=dp;
ri=r1;
ci=start;
rj=r2;
cj=i;
}
}
}
}
return {ri,ci,rj,cj};
}
};