leetcode 53 最大子序和 and 面试题 17.24. 最大子矩阵(DP)

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};
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值