通过率 73% · 提交 283 · 通过 206
小慕正在处理一个二维整数矩阵,他需要从这个矩阵中选出一个,使得这个子矩阵内所有数字的和尽可能大。 这个子矩阵被称为“”,选取的原则是:子矩阵必须是原矩阵中一段。
这类题属于华为 OD 机考真题方向中「100分 / 2024E」方向的高频题型,通常考察对「100分 / 2024E」的建模能力与边界条件处理。掌握本题的解题思路后,可举一反三应对同类真题方向,稳步提升机考通过率。
提示:带虚线的词点一下有通俗解释。
输入的第一行包含两个整数N,M (1 <= N,M <= 10)
表示一个 N 行 M 列的矩阵
下面有N行
每行有M个整数
同一行中每两个数字之间有一个空格
最后一个数字后面没有空格
所有的数字得在-1000 ~ 1000之间
输出一行,一个数字。表示选出的“和最大子矩阵”内所有数字的和
示例 1
输入示例
3 4 -3 5 -1 5 2 4 -2 4 -1 3 -1 3
输出示例
20
一个3*4的矩阵中 后面3列的和为20,和最大
时间限制 1000 ms · 内存限制 128 MB
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。
相关图解步骤
先看指定步骤补关键知识点,再回到本题完成标准输入输出。
一个子矩阵可以由四个参数决定,分别为上底、下底、左宽、右宽,分别用变量 a、b、c、d 表示。
如果要枚举所有子矩阵,只需要分别枚举 a、b、c、d,写一个 4 层嵌套的 for 循环即可:
暴力解法很容易想到:枚举所有子矩阵,然后对每个子矩阵内所有元素求和。其核心代码如下:
这里会出现 6 层 for 循环嵌套,时间复杂度较高。由于数据范围为 (1 <= n, m <= 10),取最大值时复杂度约为 O(n³·m³)。在数据量较大时可能无法通过全部用例,因此需要思考如何优化。
> 注意:该方法与 经典题型「二维区域和检索 - 矩阵不可变」类似。
每个子矩阵的和都可以通过以下方式拆解:
拆解后的四个区域有一个共同特点:它们的上底均为上边界、左宽均为左边界。
因此,可以借鉴一维前缀和的思路,将所有上底为上边界、左宽为左边界(即 a = 0,c = 0)的子矩阵的和提前记录在二维前缀和矩阵 pre_sum_mat 中。
pre_sum_mat 是一个大小为 (n+1) * (m+1) 的矩阵,其中 pre_sum_mat[i][j] 表示以第 0 行、第 0 列为开头(闭区间),第 i 行、第 j 列为结尾(开区间)的子矩阵的和。
上述四个区域的和可以分别用以下方式表示:
pre_sum_mat[b+1][d+1]pre_sum_mat[b+1][c]pre_sum_mat[a][d+1]pre_sum_mat[a][c]> 对开/闭区间的理解非常重要,如果理解不清,后续代码很容易出错。
如果把子矩阵用类似切片的方式(不严谨写法)表示为 mat[a:b+1][c:d+1],那么上述分析过程可以写成:
因此,在原矩阵 mat 中,以 a、b、c、d 分别为上底、下底、左宽、右宽的子矩阵的和可以记为:
上述计算的时间复杂度为 O(1),因此这种方法规避了暴力解中子矩阵求和时的重复计算,降低了最内层求和的时间复杂度。加上外层循环后,代码如下:
如果不想让最内层的索引出现 +1,可以修改 for 循环的范围:
上述过程的时间复杂度为 O(n²·m²)。当 n、m 取最大值时,复杂度约为 10⁴,可以通过全部用例。
二维前缀和矩阵 pre_sum_mat 的构建也要用到类似的拆分过程,其核心代码如下:
要特别注意,二维前缀和 pre_sum_mat 的大小在两个维度上均比原矩阵 mat 大 1。该过程的时间复杂度为 O(n·m)。
解法一:二维前缀和
登录后可查看你在本题的历史提交,以及每次的各用例通过情况。
© 2026 广州慕课网络科技有限公司 · 吴师兄学算法官网 版权所有