开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情
最大子矩阵(单串动态规划)
题目描述
给定一个正整数、负整数和 0 组成的 N × M 矩阵,编写代码找出元素总和最大的子矩阵。返回一个数组 [r1, c1, r2, c2],其中 r1, c1 分别代表子矩阵左上角的行号和列号,r2, c2 分别代表右下角的行号和列号。若有多个满足条件的子矩阵,返回任意一个均可。
示例
//输入
[ [-1,0],
[0,-1]
]
//输出
[0,1,0,1]
思路分析
- i 记录开始行,从0开始~最后一行
- j 记录结束行,从i开始~最后一行
- 计算 i 行~ j 行中各列元素的和存储到以数组中
- 此时二维问题化成一维问题,即求矩阵的最大<==>求列和数组的最大子序列
图解
代码实现
//记录坐标,所以不能直接使用max函数
class Solution {
public:
vector<int> getMaxMatrix(vector<vector<int>>& matrix) {
//获取n行m列
int n=matrix.size(),m=matrix[0].size();
//sum记录i行~j行的列和数组中各子段的和
int sum=0;
//分别记录开始列坐标、开始行坐标和最大值(注:最大值不能设0,要设足够小,因为矩阵中会有负数)
int be_col=0,be_row=0,maxnum=INT_MIN;
//列和数组和记录坐标数组
vector<int> col_sum(m),local(4);
//i控制开始行
for(int i=0;i<n;i++){
//每次开始行变动,列和数组就更新为0
for(int t=0;t<m;t++ ) col_sum[t]=0;
//j控制结束行
for(int j=i;j<n;j++){
//每次结束行向下移动一层,记录列和数组的sum就更新为0
sum=0;
//j向下移动一层之后,各列和只需在原来的基础上加上最下面一行的各列元素
for(int c=0;c<m;c++)
//计算出i行~j行的列和数组
col_sum[c]+=matrix[j][c];
//求最大矩阵等价于求列和数组的最大子段和,并记录位置
for(int k=0;k<m;k++){
//k值记录列元素
if(sum>0)
sum+=col_sum[k];
else{
sum=col_sum[k];
be_col=k;
be_row=i;}
if(sum>maxnum){
maxnum=sum;
local[0]=be_row;
local[1]=be_col;
local[2]=j;
//结束列即当前列
local[3]=k;}
}
}
}
return local;
}
};