线性动态规划:最大子矩阵和问题
字数 1090 2025-12-01 19:14:10

线性动态规划:最大子矩阵和问题

我将为您详细讲解最大子矩阵和问题,这是一个经典的二维动态规划问题,能够有效扩展一维最大子数组和的思想。

问题描述

给定一个m×n的整数矩阵,找出其中元素和最大的子矩阵,返回这个最大和。

示例:

输入矩阵:
[
  [1,  2, -1, -4, -20],
  [-8, -3, 4,  2,  1],
  [3,  8, 10, 1,  3],
  [-4, -1, 1,  7, -6]
]
最大子矩阵和为:29
对应子矩阵为从第2行到第3行,第2列到第4列的区域

解题思路

这个问题可以转化为多个一维最大子数组和问题来解决:

  1. 核心思想:将二维问题压缩成一维问题
  2. 关键步骤:枚举所有可能的行范围,对于每个行范围,将多行压缩成一行,然后在这个压缩后的一维数组上求最大子数组和

详细解题过程

步骤1:理解一维最大子数组和

首先回顾一维最大子数组和的Kadane算法:

def max_subarray(arr):
    max_ending_here = max_so_far = arr[0]
    for i in range(1, len(arr)):
        max_ending_here = max(arr[i], max_ending_here + arr[i])
        max_so_far = max(max_so_far, max_ending_here)
    return max_so_far

步骤2:将二维问题压缩成一维

对于矩阵中的每一列,我们可以计算从第i行到第j行之间的列和:

  • 固定起始行i和结束行j
  • 对于每一列k,计算col_sum[k] = matrix[i][k] + matrix[i+1][k] + ... + matrix[j][k]
  • 这样就得到了一个一维数组col_sum,其中每个元素代表该列在行范围[i,j]内的和

步骤3:动态规划解法

def max_submatrix(matrix):
    if not matrix or not matrix[0]:
        return 0
    
    m, n = len(matrix), len(matrix[0])
    max_sum = float('-inf')
    
    # 枚举所有可能的起始行
    for i in range(m):
        # 初始化列和数组
        col_sums = [0] * n
        
        # 枚举所有可能的结束行(从i开始到m-1)
        for j in range(i, m):
            # 更新列和:将第j行的值加到对应的列和中
            for k in range(n):
                col_sums[k] += matrix[j][k]
            
            # 在当前的列和数组上应用Kadane算法
            current_sum = col_sums[0]
            max_ending_here = col_sums[0]
            
            for k in range(1, n):
                max_ending_here = max(col_sums[k], max_ending_here + col_sums[k])
                current_sum = max(current_sum, max_ending_here)
            
            # 更新全局最大和
            max_sum = max(max_sum, current_sum)
    
    return max_sum

步骤4:算法复杂度分析

  • 时间复杂度:O(m² × n)
    • 外层循环枚举起始行i:m次
    • 中层循环枚举结束行j:平均m/2次
    • 内层处理列:n次
  • 空间复杂度:O(n),用于存储列和数组

步骤5:完整示例演示

以示例矩阵为例,演示算法执行过程:

  1. 起始行i=0

    • j=0: col_sums = [1, 2, -1, -4, -20],最大子数组和=3
    • j=1: col_sums = [-7, -1, 3, -2, -19],最大子数组和=3
    • j=2: col_sums = [-4, 7, 13, -1, -16],最大子数组和=20
    • j=3: col_sums = [-8, 6, 14, 6, -22],最大子数组和=26
  2. 起始行i=1

    • j=1: col_sums = [-8, -3, 4, 2, 1],最大子数组和=6
    • j=2: col_sums = [-5, 5, 14, 3, 4],最大子数组和=22
    • j=3: col_sums = [-9, 4, 15, 10, -2],最大子数组和=29 ← 找到最大值
  3. 继续其他起始行,但不会超过29

进阶优化

对于m远大于n的情况,可以优化为O(n² × m)的时间复杂度,通过枚举列范围而不是行范围。

总结

最大子矩阵和问题通过巧妙的维度压缩技巧,将二维问题转化为多个一维问题来解决。这种"枚举+压缩"的思想在很多二维动态规划问题中都有应用,是解决复杂问题的有效策略。

线性动态规划:最大子矩阵和问题 我将为您详细讲解最大子矩阵和问题,这是一个经典的二维动态规划问题,能够有效扩展一维最大子数组和的思想。 问题描述 给定一个m×n的整数矩阵,找出其中元素和最大的子矩阵,返回这个最大和。 示例: 解题思路 这个问题可以转化为多个一维最大子数组和问题来解决: 核心思想 :将二维问题压缩成一维问题 关键步骤 :枚举所有可能的行范围,对于每个行范围,将多行压缩成一行,然后在这个压缩后的一维数组上求最大子数组和 详细解题过程 步骤1:理解一维最大子数组和 首先回顾一维最大子数组和的Kadane算法: 步骤2:将二维问题压缩成一维 对于矩阵中的每一列,我们可以计算从第i行到第j行之间的列和: 固定起始行i和结束行j 对于每一列k,计算 col_sum[k] = matrix[i][k] + matrix[i+1][k] + ... + matrix[j][k] 这样就得到了一个一维数组 col_sum ,其中每个元素代表该列在行范围[ i,j ]内的和 步骤3:动态规划解法 步骤4:算法复杂度分析 时间复杂度 :O(m² × n) 外层循环枚举起始行i:m次 中层循环枚举结束行j:平均m/2次 内层处理列:n次 空间复杂度 :O(n),用于存储列和数组 步骤5:完整示例演示 以示例矩阵为例,演示算法执行过程: 起始行i=0 : j=0: col_ sums = [ 1, 2, -1, -4, -20 ],最大子数组和=3 j=1: col_ sums = [ -7, -1, 3, -2, -19 ],最大子数组和=3 j=2: col_ sums = [ -4, 7, 13, -1, -16 ],最大子数组和=20 j=3: col_ sums = [ -8, 6, 14, 6, -22 ],最大子数组和=26 起始行i=1 : j=1: col_ sums = [ -8, -3, 4, 2, 1 ],最大子数组和=6 j=2: col_ sums = [ -5, 5, 14, 3, 4 ],最大子数组和=22 j=3: col_ sums = [ -9, 4, 15, 10, -2 ],最大子数组和=29 ← 找到最大值 继续其他起始行,但不会超过29 进阶优化 对于m远大于n的情况,可以优化为O(n² × m)的时间复杂度,通过枚举列范围而不是行范围。 总结 最大子矩阵和问题通过巧妙的维度压缩技巧,将二维问题转化为多个一维问题来解决。这种"枚举+压缩"的思想在很多二维动态规划问题中都有应用,是解决复杂问题的有效策略。