动态规划—最大子矩阵(leetcode 面试题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

算法分析

问题从一维变成了二维,但实质是一样的,同样是再求最大子序和,我们需要将二维转化为一维,对于矩阵的每一列,我们将其加在一起,成为了一维上的一个数,二维矩阵的和转化为了一维数组的和

 

这样我们就将二维问题转化为了一维问题,现在另一个问题就是怎么把所有情况都遍历到呢?

我们以第i行为第一行,向下延申,设最后一行为第j行,我们就i在这么一个范围内,将二维问题转化为一维问题,再求解最大子序列和

 我们将当前i~j行组成的矩阵的每一列的和存放在数组b中,其余的工作就是在求最大子序列和,并且保存其左上角和右下角

代码

class Solution {
public:
    vector<int> getMaxMatrix(vector<vector<int>>& matrix) {

        int rows=matrix.size(), cols=matrix[0].size();
        int maxMat=INT32_MIN;
        vector<int> ans(4, -1);

        for(int r1=0;r1<rows;++r1){//遍历起始行
            vector<int> nums(cols);//矩阵某两行间元素按列求和
            for(int r2=r1;r2<rows;++r2){//遍历结束行

                //最大字段和问题
                int dp=0, c1=-1;
                for(int c2=0;c2<cols;++c2){//遍历和数组,实际上是边遍历边完成求和
                    nums[c2]+=matrix[r2][c2];//将新的一行中第i个元素加到前面若干行在位置i的和
                    if(dp>0){//前面的字段有和为正,可以把前面一部分也带上
                        dp+=nums[c2];
                    }
                    else{//前面一段为负,拖后腿直接抛弃
                        dp=nums[c2];
                        c1=c2;
                    }
                    if(dp>maxMat){//不断记录较好的结果
                        maxMat=dp;
                        ans[0]=r1;
                        ans[1]=c1;
                        ans[2]=r2;
                        ans[3]=c2;
                    }
                }
            }
        }
        return ans;
    }
};

算法复杂度分析

时间复杂度:o(n^2*m)

空间复杂度:o(m)

m = rows, n = cols  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值