当前位置: 首页 > news >正文

LeetCode 1074:元素和为目标值的子矩阵数量

LeetCode 1074:元素和为目标值的子矩阵数量

在这里插入图片描述

问题定义与核心挑战

给定二维矩阵 matrix 和目标值 target,需统计 所有和为 target 的非空子矩阵数量。直接枚举所有子矩阵的时间复杂度为 O(m²n²)mn 为矩阵行列数),无法通过大数据用例,因此需要降维优化

核心思路:二维转一维 + 前缀和哈希表

将二维问题转化为多个一维子问题

  1. 固定上下边界:遍历所有可能的上边界 top 和下边界 bottom,将两边界之间的列和压缩为一维数组 colSumcolSum[col] 表示 topbottom 行、第 col 列的和)。
  2. 一维子数组统计:对 colSum 数组,使用前缀和 + 哈希表的方法,统计和为 target 的子数组数量(时间复杂度 O(n))。

算法步骤详解

步骤 1:遍历上下边界
  • 枚举所有可能的上边界 top(从第 0 行到第 m-1 行)。
  • 对每个 top,初始化 colSum 数组(记录列和),并枚举下边界 bottom(从 top 到第 m-1 行)。
步骤 2:更新列和数组 colSum

对于当前 bottom,将 matrix[bottom][col] 累加到 colSum[col] 中,得到 topbottom 行的列和。

步骤 3:统计一维子数组和为 target 的数量

colSum 数组,使用前缀和 + 哈希表

  • 前缀和 currentSum:记录当前遍历到第 col 列时的前缀和(前 col+1 列的和)。
  • 哈希表 prefixCounts:记录前缀和出现的次数(初始时 prefixCounts.put(0, 1),表示前缀和为 0 的情况,对应子数组从第 0 列开始)。
  • 对于每个列和 num
    • 计算 need = currentSum - target,若 need 存在于 prefixCounts,则累加对应次数(即存在以当前列为结尾的子数组和为 target)。
    • 更新 currentSum 并记录到 prefixCounts 中。

完整代码(Java)

import java.util.HashMap;
import java.util.Map;class Solution {public int numSubmatrixSumTarget(int[][] matrix, int target) {int m = matrix.length;int n = matrix[0].length;int ans = 0;// 枚举上边界 topfor (int top = 0; top < m; top++) {int[] colSum = new int[n]; // 记录当前上下边界之间的列和// 枚举下边界 bottom(从 top 开始,逐步扩展)for (int bottom = top; bottom < m; bottom++) {// 更新列和:加上当前行 bottom 的元素for (int col = 0; col < n; col++) {colSum[col] += matrix[bottom][col];}// 统计当前 colSum 中,和为 target 的子数组数量ans += countSubarrays(colSum, target);}}return ans;}/*** 统计一维数组 nums 中,和为 target 的子数组数量* 使用前缀和 + 哈希表优化,时间复杂度 O(n)*/private int countSubarrays(int[] nums, int target) {int count = 0;int currentSum = 0;Map<Integer, Integer> prefixCounts = new HashMap<>();prefixCounts.put(0, 1); // 初始状态:前缀和为 0 出现 1 次(对应空数组)for (int num : nums) {currentSum += num;// 寻找是否存在前缀和为 currentSum - target 的情况int need = currentSum - target;if (prefixCounts.containsKey(need)) {count += prefixCounts.get(need);}// 更新当前前缀和的出现次数prefixCounts.put(currentSum, prefixCounts.getOrDefault(currentSum, 0) + 1);}return count;}
}

复杂度分析

  • 时间复杂度O(m²n)

    • 外层遍历上下边界:O(m²)m 行,每行最多遍历 m 次)。
    • 内层处理列和与一维子数组:O(n)(每轮列和更新 O(n),一维统计 O(n))。
      总复杂度为 O(m² × n),对于 m=100n=100,计算量为 100²×100=1e6,高效可行。
  • 空间复杂度O(n)

    • colSum 数组和哈希表最多占用 O(n) 空间(n 为列数)。

示例验证

示例 1(输入 matrix = [[0,1,0],[1,1,1],[0,1,0]], target = 0):
  • top=0bottom=0 时,colSum = [0,1,0],统计得 2 个 子数组([0][0])。
  • top=2bottom=2 时,colSum = [0,1,0],同样统计得 2 个 子数组。
  • 总数量为 2+2=4,符合示例输出。
示例 2(输入 matrix = [[1,-1],[-1,1]], target = 0):
  • top=0bottom=1 时,colSum = [0,0],统计得 3 个 子数组([0][0,0][0])。
  • 结合其他边界组合,最终总数量为 5,符合示例输出。

该方法通过二维转一维前缀和哈希表,高效将复杂度从 O(m²n²) 降至 O(m²n),是处理二维子矩阵和问题的经典优化思路。

http://www.xdnf.cn/news/1192879.html

相关文章:

  • 使用Spring Boot创建Web项目
  • 学习嵌入式的第三十二天-数据结构-(2025.7.24)IO多路复用
  • 开发者说|RoboTransfer:几何一致视频世界模型,突破机器人操作泛化边界
  • 1. Qt多线程开发
  • SpringMVC——建立连接
  • OpenFeign-远程调用
  • 计算机中的数据表示
  • Windows Server系统安装JDK,一直卡在“应用程序正在为首次使用作准备,请稍候”
  • Java程序员学从0学AI(六)
  • 框架式3D打印机结构设计cad【9张】三维图+设计说明书
  • openmv特征点检测
  • 如何使用Anaconda(miniconda)和Pycharm
  • Java 大视界 -- Java 大数据在智能安防视频监控系统中的视频语义理解与智能检索进阶(365)
  • x86汇编语言入门基础(三)汇编指令篇5 串操作
  • Windows11下和Vmware中的Ubuntu22.04设置samba服务遇到的一个问题- valid users和guest设置冲突
  • 零基础学习性能测试第三章:jmeter构建性能业务场景
  • java网络请求工具类HttpUtils
  • 智慧水库管理系统中标签工厂的建立方案
  • HTTP 协议的基本格式和 fiddler 的用法
  • PHP语法高级篇(六):面向对象编程
  • 可调谐激光器原理与设计 【DFB 与 DBR 激光器剖析】
  • 详解力扣高频SQL50题之1141. 查询近30天活跃用户数【简单】
  • 【区块链安全】DeFi协议安全漏洞深度分析:从闪电贷攻击到MEV套利
  • Nuxt 4:前端开发的全新篇章
  • java集合框架面试点(2)
  • 【C语言进阶】程序环境和预处理
  • 各种前端框架界面
  • HighlightingSystem
  • 精密全波整流电路(四)
  • Linux 如何统计系统上各个用户登录(或者登出)记录出现的次数?