矩形子数组的最大和

letcode 304 给定一个二维矩阵,计算其子矩形范围内元素的总和 ,53 最大和的连续子数组 304 题目:给定一个二维矩阵,计算其子矩形范围内元素的总和, 该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2) 解答思路 : 对于不在边界的任何一点 他 对应 起点 (0,0)的和 始终有一个确定的公式 : f(n,n) = f(n-1,n)+ f(n,n-1)- f(n-1,n-1); 这样 ,在一开始的时候,我们就能计算任意一点 到起点的和了。最后要得到 ... 阅读详情
——接上篇。


问题:给定m*n的矩阵,求具有最大和的矩形子数组。

先上暴力算法,求出所有矩形子数组的和,记录其中最大值。思路就是从1*1的最小子矩阵开始(m*n个),到m*n的最大子矩阵(一个)结束,求出每个子矩阵的和,找出最大值。


/** @brief  在m*n的矩阵a中查找最大子矩阵的和
 ** @note   使用一维数组代替二维数组,
 **         元素a[i][j] = a[i*n+j].
 ** @return 最大子数组的和
 ** @author quickSort,
 ** @date   2013/08/10
 **      原创文章,转载请注明出处:  http://blog.youkuaiyun.com/fastsort/article/details/9874151 
 */
int maxSubMatrix_BF(int *a, int m, int n)
{
    int mm=NM,sum=0;
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++)
        {///for all a[i][j]
            for(int ii=i;ii<m;ii++)
            {
                for(int jj=j;jj<n;jj++)
                {
                    sum = 0;
                    for(int ti=i; ti<=ii;ti++)
                        for(int tj=j; tj<=jj;tj++)
                        {
                            sum += a[ti*n+tj];///a[ii][jj] ///sum of a[i][j] -> a[ii][jj]
                        }
                    mm  = max(sum,mm);
                }
            }
        }
    }
    cout<<__FUNCTION__<<": "<<mm<<endl;
    return m;
}


为了使矩形的2维都可以是变量,这里使用一维数组模拟二维矩阵,m*n的矩阵中元素a[i][j]对应于数组中的值就是a[i*n+j]。
其复杂度是多少呢……?一眼看去,6个for循环,OMG。。。像是O(m3n3).
显然,复杂度太高了。。。。


===================================================================================================
结合一维最大子数组,可以这么考虑:二维矩阵在某种程度上可以看做一位数组,而一维数组的每个元素又是一维数组。对于一维数组,最大子数组的和我们已经可以在O(n)内求出,而不需要O(n2)。

这里再回忆一下这两个算法:


平方算法:
///算法1.
///在数组a[n]中找出子数组的最大和
void    maxSum_1(int a[], int n)
{
    int sum=NM,m=NM;//NM是一个很小的负数,例如-99999999.下同
    for(int i=0; i<n; i++)
    {
        sum=0;
        for(int j=i; j<n; j++)
        {
            sum += a[j];
            m = max(m,sum);
        }
    }
    cout<<__FUNCTION__<<" : "<<m<<endl;
}

扫描算法:

///算法2,扫描算法
///在数组a[n]中找出子数组的最大和
void    maxSum_3(int a[], int n)
{
    int maxSoFar=NM, maxEndingHere=NM;
    for(int i=0; i<n; i++)
    {
        maxEndingHere = max(maxEndingHere+a[i], a[i]);
        maxSoFar = max(maxSoFar,maxEndingHere);
    }
    cout<<__FUNCTION__<<" : "<< maxSoFar <<endl;
}


对于行向量(m个),使用普通的平方算法,即算法1,
对于列向量(n个),使用扫描算法,即算法2。
具体代码如下:

/** @brief  在m*n的矩阵a中查找最大子矩阵的和
 ** @note   使用一维数组代替二维数组,
 **         元素a[i][j] = a[i*n+j].
 ** @return 最大子数组的和
 ** @author quickSort,
 ** @date   2013/08/10
 **         原创文章,转载请注明出处:  http://blog.youkuaiyun.com/fastsort/article/details/9874151 
 */
int maxSubMatrix(int *a, int m, int n)
{
    int i,j,k;
    int maxSoFar=NM,maxEndingHere;
    int *sum = (int*)malloc(sizeof(int)*n);
    for(i=0;i<m;i++)
    {
        memset(sum,0,sizeof(int)*n);///sum=0
        for(j=i;j<m;j++)///在m维度上使用平平方算法
        {
            maxEndingHere = 0;
            for(k=0;k<n;k++)///在n维度上使用扫描算法
            {
                sum[k] += a[j*n+k];///a[j*n+k]=a[j][k]
                maxEndingHere=max(maxEndingHere+sum[k],sum[k]);
                maxSoFar = max(maxSoFar,maxEndingHere);
            }
        }
    }
    free(sum);
    cout<<__FUNCTION__<<" : "<<maxSoFar<<endl;
    return maxSoFar;
}


其复杂度为O(m2n)。

完整测试代码:


#include    <iostream>
#include    <algorithm>
#include    <cstring>
///
/** @brief  矩形子数组的最大和 完整测试代码
 ** @author quickSort,
 ** @date   2013/08/10
 **         原创文章,转载请注明出处:  http://blog.youkuaiyun.com/fastsort/article/details/9874151 
 **         
 */

using namespace std;

int d[] = {-3,-2,-67,-7,-9,-8};
int c[] = {1,-2,3,10,-4,7,2,-5};
int e[] =   /// 2*8 || 4*4
            { 1,-2, 3,10,
             -4, 7, 2,-5,
              1,-8,-5,-9,
              7,10,-6,-20
            };
const int   NM = -99999;

void    maxSum_1(int a[], int n)
{
    int sum=NM,m=NM;
    for(int i=0; i<n; i++)
    {
        sum=0;
        for(int j=i; j<n; j++)
        {
            sum += a[j];
            m = max(m,sum);
        }
    }
    cout<<__FUNCTION__<<" : "<<m<<endl;
}

void    maxSum_3(int a[], int n)
{
    int maxSoFar=NM, maxEndingHere=NM;
    for(int i=0; i<n; i++)
    {
        maxEndingHere = max(maxEndingHere+a[i], a[i]);
        maxSoFar = max(maxSoFar,maxEndingHere);
    }
    cout<<__FUNCTION__<<" : "<< maxSoFar <<endl;
}

template  <typename T>
inline  T   abs(T n)
{
    return  n<0?(-n):n;
}

///-----------------------------------------
/** @brief  在m*n的矩阵a中查找最大子矩阵的和
 ** @note   使用一维数组代替二维数组,
 **         元素a[i][j] = a[i*n+j].
 ** @return 最大子数组的和
 ** @author quickSort,
 ** @date   2013/08/10
 **
 */
int maxSubMatrix(int *a, int m, int n)
{
    int i,j,k;
    int maxSoFar=NM,maxEndingHere;
    int *sum = (int*)malloc(sizeof(int)*n);
    for(i=0;i<m;i++)
    {
        memset(sum,0,sizeof(int)*n);///sum=0
        for(j=i;j<m;j++)
        {
            maxEndingHere = 0;
            for(k=0;k<n;k++)
            {
                sum[k] += a[j*n+k];///a[j*n+k]=a[j][k]
                maxEndingHere=max(maxEndingHere+sum[k],sum[k]);
                maxSoFar = max(maxSoFar,maxEndingHere);
            }
        }
    }
    free(sum);
    cout<<__FUNCTION__<<" : "<<maxSoFar<<endl;
    return maxSoFar;
}
/** @brief  在m*n的矩阵a中查找最大子矩阵的和
 ** @note   使用一维数组代替二维数组,
 **         元素a[i][j] = a[i*n+j].
 ** @return 最大子数组的和
 ** @author quickSort,
 ** @date   2013/08/10
 **
 */
int maxSubMatrix_BF(int *a, int m, int n)
{
    int mm=NM,sum=0;
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++)
        {///for all a[i][j]
            for(int ii=i;ii<m;ii++)
            {
                for(int jj=j;jj<n;jj++)
                {
                    sum = 0;
                    for(int ti=i; ti<=ii;ti++)
                        for(int tj=j; tj<=jj;tj++)
                        {
                            sum += a[ti*n+tj];///a[ii][jj] ///sum of a[i][j] -> a[ii][jj]
                        }
                    mm  = max(sum,mm);
                }
            }
        }
    }
    cout<<__FUNCTION__<<": "<<mm<<endl;
    return m;
}

int main()
{
    int n   = sizeof(c)/sizeof(int);
    int a[100];
    reset(a,n);
    maxSum_1(a,n);

    maxSum_3(a,n);

    maxSubMatrix(e,4,4);
    maxSubMatrix_BF(e,4,4);
    return 0;
}



结果:
maxSum_1 : 18
maxSum_3 : 18
maxSubMatrix : 17
maxSubMatrix_BF: 17


Process returned 0 (0x0)   execution time : 0.296 s
Press any key to continue.





动态规划问题系列---连续子数组(二维)的最大和 题目1一维数组的连续子数组的最大和 输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。要求时间负责度为O(n)。分析假如输入数组为{1,-2,3,10,-4,7,2,-5},我们尝试从头到尾累加其中的正数,初始化和为0,第一步加上1,此时和为1,第二步加上-2,此时和为-1,第三步加上3,此时我们发现-1+3=2,最大和2反而比3一个单独的 阅读详情

相关推荐

VS2022打包C#安装包(最新、最全)

VS2022打包C#安装包(最新、最全)

qq_37959253的博客 9893

dp解法 leetcode 363.矩形区域不超过 K 的最大数值和

题目: 给你一个 m x n 的矩阵 matrix 和一个整数 k ,找出并返回矩阵内部矩形区域的不超过 k 的最大数值和。 题目数据保证总会存在一个数值和不超过 k 的矩形区域。 示例 1: 输入:matrix = [[1,0,1],[0,-2,3]], k = 2 输出:2 解释:蓝色边框圈出来的矩形区域 [[0, 1], [-2, 3]] 的数值和是 2,且 2 是不超过 k 的最大数字(k = 2 示例 2: 输入:matrix = [[2,2,-1]], k = 3 输出:3 作者dp的结果:

ITZhaoYiSheng的博客 396

智能座舱芯片大乱斗:高通8155 vs 联发科MT8676 vs 华为麒麟990A,谁才是性价比之王?

本文深入对比了高通SA8155P、联发科MT8676与华为麒麟990A三款主流智能座舱芯片的性能、生态与成本。文章从CPU/GPU/NPU算力、开发生态、成本模型及典型应用场景出发,分析了各自在智能座舱领域的优势与适用性,为开发者与车企选型提供了实战参考,并探讨了智能座舱芯片未来的技术趋势。

yhn456789的博客 800

363. 矩形区域不超过 K 的最大数值和

给定一个非空二维矩阵matrix和一个整数k,找到这个矩阵内部不大于k的最大矩形和。 示例: 输入: matrix = [[1,0,1],[0,-2,3]], k = 2 输出: 2 解释:矩形区域[[0, 1], [-2, 3]]的数值和是 2,且 2 是不超过 k 的最大数字(k = 2)。 说明: 矩阵内的矩形区域面积必须大于 0。 如果行数远大于列数,你将如...

start_lie的博客 548

Opencv4.5.1 微信二维码识别功能 QRCode 编译与使用 C++

部分参考:https://mp.weixin.qq.com/s/2GZAJAUPHTXFOKDRv-D21Q 一、下载源码 https://github.com/opencv 二、源码编译 ① 在cmake中添加源码编译路径和生成路径,第一次点击configure。 ② 添加contrib路径 第一次configure后,找到OPENCV_EXTRA_MODULES_PATH,将contrib路径添加进来,注意要具体到modules/,继续configure。 ..

zaibeijixing的专栏 1万+

Kubernetes多网卡环境下Calico网络配置避坑指南:如何精准指定业务网卡

本文针对Kubernetes多网卡环境下Calico网络配置的常见痛点,提供了精准指定业务网卡的实战指南。通过深入分析Calico的IP自动检测机制,详细解读并对比了五种IP_AUTODETECTION_METHOD配置方法(如interface、cidr、can-reach等),帮助运维人员从根源上解决网络分区和Pod通信失败问题,确保生产集群网络的稳定与可靠。

weixin_28835551的博客 730

poj 1050 To the Max 求矩阵中局部矩形区域和最大值

题目:来源于http://poj.org/problem?id=1050 描述:给定一个矩阵,求出其包含的矩形区域的最大值(矩形区域总所包含的所有元素都要算)。具体如下:             0 -2 -7 0             9 2 -6 2       最大值区域:        9   2            -4 1 -4 1

继续微笑lsj 3239

华为防火墙介绍和原理,配置详细解析

在出向外网的流量中,我们使用默认路由来指定默认的出口,并且使用nat地址转换,而在外网中,我们使用ISIS协议来进行路由的学习和更新,让外网可以访问到dmz非军事化区域的server1服务器。并进行NAT转换,实现了内部IP地址和外部IP地址之间的映射,以便内部网络可以与外部网络进行通信。网络地址转换(NAT):防火墙可实现网络地址转换,将内部私有IP地址转换成公共IP地址,以隐藏网络拓扑结构,增加网络安全性。确定安全需求:根据企业的安全需求和策略,确定防火墙的配置目标和规则。

外游者 5097

ACM Poj1050 To the Max 求矩阵中局部矩形区域和最大值 java版本

今天又刷了一道poj上面的水题。 题目的要求大致如下: 给定一个矩阵,求出其包含的矩形区域的最大值(矩形区域总所包含的所有元素都要算)。具体如下:             0 -2 -7 0              9 2 -6 2       最大值区域:        9   2            -4 1 -4 1                           -4

zhangfeng12345677的博客 1443

拆解汽车T-Box:从4G模块到MCU,手把手教你理解车联网的‘黑匣子’

本文深入拆解汽车T-Box,揭示其作为车联网‘黑匣子’的核心架构与工作原理。从4G模块、MCU主控到外设接口,详细解析各组件功能及协同机制,并通过实战案例展示故障诊断与性能优化技巧,帮助读者全面理解T-Box在智能汽车中的关键作用。

weixin_30955617的博客 492

使用Google Earth Engine(GEE)的Python API,您可以将经纬度坐标转换为Landsat影像的路径/行号

使用Google Earth Engine(GEE)的Python API,您可以将经纬度坐标转换为Landsat影像的路径/行号。在这个示例中,我们选择了一个位于加利福尼亚州旧金山市附近的点,其经度为-122.084,纬度为37.421998。首先,我们需要导入必要的库和模块。接下来,我们定义一个函数,该函数将接收经度和纬度作为输入,并返回对应的Landsat路径/行号。最后,我们提取路径和行号的值,并将它们作为结果返回。现在,我们可以使用这个函数来获取特定点的Landsat路径/行号。

VwajAlgorithm的博客 348

【数据结构与算法】二维数组 最大矩形和

使用Kadane算法可以很方便地求解一维数组的最大连续子序列之和。 下面是Kadane算法的延伸,在二维数组中求解最大矩形。 思路是要利用一维数组的求解方法来求解二维,假设现在要求以i列开始到j列结束的最大和,不能是i和j之间的,必须以i和j是开始和结束。可以把i和j之间的列相加,最终得到一个一维数组,那么这个一维数组的最大值就是i和j的最大值,这是因为这个一维数组中存的就是每一行的和,与co

u010900754的专栏 2451

【YOLOv10改进[Backbone]】使用ADNet改进YOLOv10在噪声干扰下的目标检测效果(图像去噪)+ 含全部代码和详细修改方式 + 手撕结构图 + 全网首发

使用ADNet改进YOLOv10在噪声干扰下的目标检测效果(图像去噪)+ 含全部代码和详细修改方式 + 手撕结构图 + 全网首发 + 遥遥领先

静谧、淡雅 2857

求矩形子数组最大和

编程珠玑第八章第11题,找出m*n的数组中总和最大的子数组,可以在长度为m的维度上使用平方算法,在长度为n的维度上使用扫描算法,时间复杂度时O(m2n) int maxSubMatrix(int *a, int m, int n) { int i,j,k; int maxSoFar=NM,maxEndingHere; int *sum = (int*)malloc(siz

陆业聪 1003

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

面试题之连续子数组的最大和问题,矩形覆盖问题

bin_ge_love的博客 635

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

二维数组子数组矩形和

  在完成一维数组子数组和的最大值后,我们将目光转向了二维数组,如何求二维数组矩形子数组最大和呢?   最简单的办法:都算一遍!   是的,将所有可以构成矩形的子数组全算一遍,然后进行比较大小。这是最简单的、最麻烦的方法了。 截图如下: 代码地址:https://github.com/Evilleon/The-sum-of-the-largest-subarrays 转...

weixin_30386713的博客 262

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

二维数组求最大子数组

一维数组已经测试完了,在意料之中又来了个二维数组,那么二维数组求子数组怎么求呢,我这里有两种方法,第一种就是基于一维数组求最大子数组,二维数组类似,把第一行数求出最大子数组,第二行求出最大子数组,以此类推。。。然后两行两行上下相加求出最大子数组,三行三行相加求最大子数组,以此类推。。。最后向把所有结果存入新数组里面,用冒泡排序等一系列排序求出最大值。第二种方法就是我今天在网上学习到的新方法,这...

weixin_30576859的博客 244

dp最大区间和最大矩阵

question 1: Acwing视频讲解 输入一个 非空 整型数组,数组里的数可能为正,也可能为负。 数组中一个或连续的多个整数组成一个子数组。 求所有子数组的和的最大值。 要求时间复杂度为O(n)。 输入:8 1 -2 3 10 -4 7 2 -5 输出:18 解析:首先我们因该知道 a[ i ]前一个位置的区间最大值影响 a[ i ]位置区间最大。 我们分析数组每一个元素都为必选,对于数组里必选第i个数a[ i ], 所以到必选a[ i ] 的位置时,这时区间最大应该为 ma = max(a[

m0_46260869的博客 662

【acwing 寒假每日一题(入门组)】day22最大的和

题目描述 给定一个包含整数的二维矩阵,子矩形是位于整个阵列内的任何大小为1 * 1或更大的连续子阵列。 矩形的总和是该矩形中所有元素的总和。 在这个问题中,具有最大和的子矩形被称为最大子矩形。 例如,下列数组: 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2 其最大子矩形为: 9 2 -4 1 -1 8 它拥有最大和15。 输入格式 输入中将包含一个N*N的整数数组。 第一行只输入一个整数N,表示方形二维数组的大小。 从第二行开始,输入由空格和换行符隔开的N2个整数,它们即为二

可乐大牛的博客 169

Dynamic Programming(动态规划算法题总结)

写在前面 暑假也是闲来无事,就想做做动态规划的题。想想在过去不久的第十届蓝桥杯国赛经历,几乎全是动态规划的题,虽然有个别题可以用深搜广搜解决,但是能过的样例不超过30%,都会超时的。因此我想总结一下。希望不会让我掉头发,这太烧脑了… 1.矩形覆盖 我们可以用2 * 1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2 * 1的小矩形无重叠地覆盖一个2 * n的大矩形,总共有多少种方法? 思路 这个...

小白的Coding之旅 342

前缀和

用于本人复习的前缀和文章 前缀和 一维数组的应用 对于一个数组nums,我们设定一个前缀和数组p_m。p_m数组中的元素含义为p[i] = nums[0]+nums[1]+…nums[i]. 一般更新方式为p[i] = p[i-1]+nums[i] 在刷题过程中往往会遇到一类问题,暴力做法可能需要枚举一个整体的所有子可能;例如一个字符串的所有字串。根据具体需要,可能前缀和将会起到帮助作用,降低时间复杂度。 假如nums = [1,2,3,-2,5,-7,-5,10],我们需要求得他连续子数组的最大和。

qq_45554539的博客 303

动态规划问题

关于动态规划的问题

kx2160841406的博客 1956

矩阵区域不超过K的最大值和

矩阵区域不超过K的最大值和 问题描述: 给你一个 m x n 的矩阵 matrix 和一个整数 k ,找出并返回矩阵内部矩形区域的不超过 k 的最大数值和。题目数据保证总会存在一个数值和不超过 k 的矩形区域。 输入:matrix = [[1,0,1],[0,-2,3]], k = 2 输出:2 输入:matrix = [[2,2,-1]], k = 3 输出:3 思路:记 l,rl , rl,r分别为matrix的可移动左右边界(l:0−col,r:l−coll:0-col, r: l-coll:0−c

qq_34233136的博客 311

UVA--10827 Maximum sum on a torus

A grid that wraps both horizontally and vertically is called a torus. Given a torus where each cell contains an integer, determine the sub-rectangle with the largest sum. The sum of a sub-rectangle is

Ac_try的专栏 494

leetcode 53、633 最大子序和、矩阵区域不超过K的最大数值和(类似动态规划之数值和的比较)

题目描述: 53:给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4] 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 363:给定一个非空二维矩阵 matrix 和一个整数 k,找到这个矩阵内部不大于 k 的最大矩形和。 示例: 输入: matrix = [[1,0,1],[0,-2,3]], k = 2 输出: 2 解释: 矩形区域 [[0, 1], [-2, 3]

peachzy的博客 226

c++动态规划类算法编程汇总(四)集合的子集|最长子序列(矩阵)的和(积) | 最大子矩阵

目录 一、集合的子集合 1.1 回溯法思路 1.2 回溯法代码及解析 1.3 其他人思路及代码供参考 1.4 分治法(动态规划) 1.5 位运算法实现穷举 二、连续子数组的最大和 2.1 类似股票最大值 2.2 推算方法 2.3 动态规划方法 三、最大子矩阵和 3.1 题干 3.2 错误的积分图的方法 3.3 在连续子数组基础上更改 四、直方图中面积最大的矩形 4....

祥瑞的技术博客 1505
上一篇: 最大子数组问题——编程珠玑第八章
下一篇: kmp算法(上)
quickSort
博客等级 码龄15年 51粉丝 57原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值