面试题 17.24. 最大子矩阵(动态规划)

面试题 17.24. 最大子矩阵

问题描述

难度困难154收藏分享切换为英文接收动态反馈

给定一个正整数、负整数和 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

思路

我们之前解决过一维数组的最大和问题,回顾一下就是规定长度为i的数组的最大和为dp[i]。则有
d p [ i ] = n u m s [ i ] ( d p [ i − 1 ] < 0 ) dp[i]=nums[i](dp[i-1]<0) dp[i]=nums[i](dp[i1]<0)

d p [ i ] = n u m s [ i ] + d p [ i − 1 ] ( d p [ i − 1 ] > = 0 ) dp[i]=nums[i]+dp[i-1](dp[i-1]>=0) dp[i]=nums[i]+dp[i1](dp[i1]>=0)

显然这个题目是一个二维问题,那么我们就把它压缩成一维,然后再用上面的求解一维的方法,我们规定i是压缩的二维数组的起始行,j是压缩二维数组的结束行,那么那么我们需要遍历i和j;

得到一个一维数组,然后寻找最大子序列的和,并记录这个最大子序列和的起始位置和结束位置,然后算出的最大值再去和一个全局最大值比较,如果超过他那么更新r1,r2,c1,c2

代码演示:

class Solution {
public:
    vector<int> getMaxMatrix(vector<vector<int>>& matrix) 
    {int r1=0,C1=0,r2=0,C2=0;
    int n=matrix.size();
    int column=matrix[0].size();
    //将从第i行到第j行的矩阵压缩到一维
    int sum=matrix[0][0];

    for(int i=0;i<n;i++)//这里的i为起始行
    {  vector<int> line(column,0);
        for(int j=i;j<n;j++)//这里的j为结束行
        {//清空线性数组
         
               
           int he=matrix[0][0];
           int c1=0;//暂存列起始位置
           int c2=0;//暂存列结束位置
           int sum2=matrix[0][0];
            vector<int>dp(column,0);
                int cc1=0;
                vector<int>dp_xiabiao(column,0);
           for(int k=0;k<column;k++)
            {  

                    line[k]+=matrix[j][k];
                 
              
             int temp=he+line[k];
                 if(temp>=line[k])
                 { he=he+line[k];
                    dp[k]=he;
                    dp_xiabiao[k]=cc1;
                 }
                 else
                 {
                    cc1=k;
                  //  cout<<"cc1 is" <<cc1<<endl;
                    dp[k]=line[k];
                    he=line[k];
                    dp_xiabiao[k]=cc1;
                 }
             }   

                  for(int s=0;s<column;s++)
                  {//cout<<dp_xiabiao[s]<<" "<<"dp is"<<dp[s]<<" ";
                    if(dp[s]>sum2)
                    {
                        c1=dp_xiabiao[s];
                        c2=s;
                        sum2=dp[s];
                    }
                  }
                 // cout<<endl;
   
                 if(sum2>sum)
                 {//压缩后的数组的值大于了sum值那么就进行四个值的更新
                      sum=sum2;
                      r1=i;
                      r2=j;
                      C1=c1;
                      C2=c2;
                 }
                 
        }
    }
vector<int>answer;
answer.push_back(r1);
answer.push_back(C1);
answer.push_back(r2);
answer.push_back(C2);
return answer;

    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜业

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值