目标值子矩阵的数量

目标值子矩阵的数量

问题描述

小M最近在研究矩阵,他对矩阵中的子矩阵很感兴趣。给定一个矩阵 matrix 和一个目标值 target,他的任务是找到所有总和等于目标值的非空子矩阵的数量。子矩阵通过选择矩阵的某个矩形区域定义,形式为 (x1, y1, x2, y2),其中 (x1, y1) 表示左上角的坐标,(x2, y2) 表示右下角的坐标。一个子矩阵包含矩阵中所有位于这个矩形区域内的单元格。如果两个子矩阵的坐标不同(如 x1 != x1' 或 y1 != y1'),则这两个子矩阵被认为是不同的。

你需要返回满足条件的子矩阵数量。

测试样例

样例1:

输入:matrix = [[-1,1,0], [1,1,1], [0,1,0]] ,target = 0

输出:7

样例2:

输入:matrix = [[-1,-1], [-1,1]] ,target = 0

输出:2

样例3:

输入:matrix = [[-1,2,3], [4,5,6], [7,8,9]] ,target = 10

输出:2

题解

二维前缀和,枚举左上角的点和右下角的点。时间复杂度O(n^2 * m^2)

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;

int solution(vector<vector<int>>& matrix, int target) {
    // PLEASE DO NOT MODIFY THE FUNCTION SIGNATURE
    // write code here
    int n = matrix.size();
    int m = matrix[0].size();
    vector<vector<int>> ans(n+1, vector<int>(m+1, 0));
    int res = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            ans[i+1][j+1] = matrix[i][j] + ans[i][j+1] + ans[i+1][j] - ans[i][j];
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            for (int r = i ; r < n; r++) {
                for (int c = j ; c < m; c++) {
                    int tmp = ans[r+1][c+1] - ans[r+1][j] - ans[i][c+1] + ans[i][j];
                    if (target == tmp) {
                        res++;
                    }
                }
            }
        }
    }
 
    return res;
}
cpp 复制代码
优化枚举左上点和右下点的枚举。使用前缀和+ 哈希表进行优化。
c++ 复制代码
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;

int solution(vector<vector<int>>& matrix, int target) {
    // PLEASE DO NOT MODIFY THE FUNCTION SIGNATURE
    // write code here
    int n = matrix.size();
    int m = matrix[0].size();
    vector<vector<int>> ans(n+1, vector<int>(m+1, 0));
    int res = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            ans[i+1][j+1] = matrix[i][j] + ans[i][j+1] + ans[i+1][j] - ans[i][j];
        }
    } 
    // top代表左上点的行号
    for (int top = 0; top< n; top++) {
        // bottom 代表右下点的行号
        for (int bottom = top; bottom < n; bottom ++) {
            // 存储前缀和的数量
            unordered_map<int, int> sumCount;
            sumCount[0] = 1;
            for (int col = 0; col < m; col++) {
                // 这里计算出来的就是[top][col] - [bottom][col]的值
                int currentSum = ans[bottom+1][col+1] - ans[top][col+1];
                // prefix[i−1]=prefix[j]−target 这个公式的提现
                if (sumCount.find(currentSum-target) != sumCount.end()) {
                    res += sumCount[currentSum-target];
                }
                sumCount[currentSum]++;
            }
        }
    }
    return res;
}
相关推荐
晨曦夜月5 分钟前
笔试强训day5
数据结构·算法
H_z___7 分钟前
Hz的计数问题总结
数据结构·算法
她说彩礼65万8 分钟前
C# 反射
java·算法·c#
练习时长一年8 分钟前
LeetCode热题100(搜索插入位置)
数据结构·算法·leetcode
hz_zhangrl9 分钟前
CCF-GESP 等级考试 2025年9月认证C++六级真题解析
c++·算法·青少年编程·程序设计·gesp·2025年9月gesp·gesp c++六级
喇一渡渡20 分钟前
Java力扣---滑动窗口(1)
java·算法·排序算法
net3m3327 分钟前
雅特力单片机用串口USART_INT_TDE中断比用USART_INT_TRAC的 发送效率要高
java·开发语言·算法
兵哥工控36 分钟前
MFC用高精度计时器实现五段时序控制器
c++·mfc·高精度计时器·时序控制器
@我漫长的孤独流浪1 小时前
程序综合实践第十二周-二叉树
算法·深度优先·图论
啊阿狸不会拉杆1 小时前
《数字图像处理》第 3 章 - 灰度变换与空间滤波
图像处理·人工智能·算法·计算机视觉·数字图像处理