0

0

优化二维最大子矩阵和问题:包含左上角单元格的快速求解方法

霞舞

霞舞

发布时间:2025-10-24 13:10:01

|

835人浏览过

|

来源于php中文网

原创

优化二维最大子矩阵和问题:包含左上角单元格的快速求解方法

本文探讨了二维最大子矩阵和问题的一个简化版本:查找必须包含矩阵左上角单元格的最大和子矩阵。针对这一特定场景,我们介绍了一种基于积分图像(Summed Area Table)的O(nm)时间复杂度的解决方案,显著优于传统O(nm^2)的Kadane算法扩展,并详细说明了如何构建积分图像以及如何从中高效地找出最优子矩阵及其和。

引言:简化版二维最大子矩阵和问题

二维最大子矩阵和问题是一个经典的算法挑战,旨在在一个给定整数矩阵中找到一个子矩阵,使其所有元素之和最大。通常,这个问题可以通过将Kadane算法(一维最大子数组和算法)扩展到二维,实现O(nm^2)或O(n^2m)的时间复杂度。然而,当问题被简化为只考虑那些必须包含矩阵左上角单元格(0,0)的子矩阵时,存在一种更为高效的O(nm)解决方案。这种简化限制使得我们能够利用积分图像(Integral Image),也称为求和面积表(Summed Area Table),来快速解决问题。

积分图像(Integral Image)原理

积分图像是一种数据结构,用于快速计算图像或矩阵中任意矩形区域的和。对于一个给定的 n x m 矩阵 M,其对应的积分图像 II 的每个单元格 II[r][c] 存储的是从原始矩阵的左上角 (0,0) 到当前单元格 (r,c) 所形成的矩形区域内所有元素的和。

积分图像的构建遵循以下递推关系: II[r][c] = M[r][c] + II[r-1][c] + II[r][c-1] - II[r-1][c-1]

其中,对于边界情况:

  • II[0][0] = M[0][0]
  • II[r][0] = M[r][0] + II[r-1][0] (对于 r > 0)
  • II[0][c] = M[0][c] + II[0][c-1] (对于 c > 0)

通过这个公式,我们可以在O(nm)的时间复杂度内构建整个积分图像。

Civitai
Civitai

AI艺术分享平台!海量SD资源和开源模型。

下载

针对简化问题的解决方案

由于我们只关心那些包含原始矩阵左上角 (0,0) 的子矩阵,这意味着任何这样的子矩阵都可以由其右下角 (r,c) 唯一确定。根据积分图像的定义,II[r][c] 正好表示了从 (0,0) 到 (r,c) 这个矩形区域内的元素和。

因此,解决简化版问题的核心思路是:

  1. 构建原始矩阵的积分图像。
  2. 在构建完成的积分图像中,找到最大的值。这个最大值就是我们所求的最大子矩阵和。
  3. 该最大值对应的坐标 (r_max, c_max) 即为最优子矩阵的右下角坐标。

算法步骤

  1. 初始化: 创建一个与原始矩阵 M 大小相同的 II 矩阵,并用零填充。
  2. 计算第一行和第一列:
    • II[0][0] = M[0][0]
    • 对于 c 从 1 到 m-1:II[0][c] = II[0][c-1] + M[0][c]
    • 对于 r 从 1 到 n-1:II[r][0] = II[r-1][0] + M[r][0]
  3. 计算其余部分:
    • 对于 r 从 1 到 n-1:
      • 对于 c 从 1 到 m-1: II[r][c] = M[r][c] + II[r-1][c] + II[r][c-1] - II[r-1][c-1]
  4. 查找最大值:
    • 初始化 max_sum = -infinity 和 max_coords = (0,0)。
    • 遍历整个 II 矩阵,更新 max_sum 和 max_coords。
    • 对于每个 II[r][c]:
      • 如果 II[r][c] > max_sum,则 max_sum = II[r][c] 且 max_coords = (r,c)。
  5. 结果: max_sum 是最大子矩阵和,max_coords 是该子矩阵的右下角坐标。最优子矩阵即为 M[0:max_coords[0]+1][0:max_coords[1]+1]。

示例代码 (Python)

import math

def max_submatrix_top_left(matrix):
    """
    查找必须包含左上角(0,0)的最大和子矩阵。

    Args:
        matrix: 一个n x m的整数矩阵。

    Returns:
        tuple: (最大和, (右下角行索引, 右下角列索引))
    """
    if not matrix or not matrix[0]:
        return 0, (-1, -1)

    n_rows = len(matrix)
    n_cols = len(matrix[0])

    # 1. 初始化积分图像 (Integral Image)
    ii = [[0] * n_cols for _ in range(n_rows)]

    # 初始化最大和及其对应的右下角坐标
    max_sum = -math.inf
    max_coords = (-1, -1)

    # 2. 计算第一行和第一列的积分图像
    ii[0][0] = matrix[0][0]
    if ii[0][0] > max_sum:
        max_sum = ii[0][0]
        max_coords = (0, 0)

    for c in range(1, n_cols):
        ii[0][c] = ii[0][c-1] + matrix[0][c]
        if ii[0][c] > max_sum:
            max_sum = ii[0][c]
            max_coords = (0, c)

    for r in range(1, n_rows):
        ii[r][0] = ii[r-1][0] + matrix[r][0]
        if ii[r][0] > max_sum:
            max_sum = ii[r][0]
            max_coords = (r, 0)

    # 3. 计算其余部分的积分图像并同时寻找最大和
    for r in range(1, n_rows):
        for c in range(1, n_cols):
            ii[r][c] = matrix[r][c] + ii[r-1][c] + ii[r][c-1] - ii[r-1][c-1]
            if ii[r][c] > max_sum:
                max_sum = ii[r][c]
                max_coords = (r, c)

    return max_sum, max_coords

# 示例用法
matrix1 = [
    [1,  2, -1],
    [-3, 4,  5],
    [6, -7,  8]
]
max_sum1, coords1 = max_submatrix_top_left(matrix1)
print(f"矩阵1: {matrix1}")
print(f"最大和子矩阵 (包含左上角) 的和: {max_sum1}, 右下角坐标: {coords1}")
# 对应的子矩阵为 matrix1[0:coords1[0]+1][0:coords1[1]+1]

matrix2 = [
    [-1, -2, -3],
    [-4, -5, -6],
    [-7, -8, -9]
]
max_sum2, coords2 = max_submatrix_top_left(matrix2)
print(f"\n矩阵2: {matrix2}")
print(f"最大和子矩阵 (包含左上角) 的和: {max_sum2}, 右下角坐标: {coords2}")

matrix3 = [
    [1, 1, 1],
    [1, -10, 1],
    [1, 1, 1]
]
max_sum3, coords3 = max_submatrix_top_left(matrix3)
print(f"\n矩阵3: {matrix3}")
print(f"最大和子矩阵 (包含左上角) 的和: {max_sum3}, 右下角坐标: {coords3}")

时间复杂度分析

  • 构建积分图像:
    • 初始化 ii 矩阵需要 O(nm) 时间。
    • 计算第一行和第一列需要 O(n + m) 时间。
    • 计算 ii 矩阵的其余部分需要 O(nm) 时间(每个单元格执行常数次操作)。
  • 查找最大值: 遍历整个 ii 矩阵需要 O(nm) 时间。

因此,整个算法的总时间复杂度为 O(nm) + O(n + m) + O(nm) + O(nm) = O(nm)。这相比于一般二维最大子矩阵和问题的 O(nm^2) 或 O(n^2m) 解决方案,在 n 和 m 较大时具有显著的性能优势。

总结

当二维最大子矩阵和问题被限定为必须包含矩阵左上角 (0,0) 时,积分图像提供了一种极其高效的解决方案。通过 O(nm) 的时间复杂度构建积分图像,并随后在 O(nm) 时间内找到最大值,我们可以快速确定最大和子矩阵及其右下角坐标。这种方法充分利用了问题简化带来的结构性优势,是处理此类特定约束问题的理想选择。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

773

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

684

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

765

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

719

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1425

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

570

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

579

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

751

2023.08.11

c++ 根号
c++ 根号

本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

25

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 17万人学习

Django 教程
Django 教程

共28课时 | 3.4万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号