目标值子矩阵的数量

目标值子矩阵的数量

问题描述

小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;
}
相关推荐
杨连江几秒前
原子级平面限域协同晶核诱导定向生长单层鳞片石墨的研究
算法
MATLAB代码顾问6 分钟前
混合粒子群-模拟退火算法(HPSO-SA)求解作业车间调度问题——附MATLAB代码
算法·matlab·模拟退火算法
Felven10 分钟前
C. Prefix Min and Suffix Max
算法
加农炮手Jinx11 分钟前
LeetCode 26. Remove Duplicates from Sorted Array 题解
算法·leetcode·力扣
加农炮手Jinx11 分钟前
LeetCode 88. Merge Sorted Array 题解
算法·leetcode·力扣
格林威11 分钟前
线阵工业相机:如何计算线阵相机的行频(Line Rate)?公式+实例
开发语言·人工智能·数码相机·算法·计算机视觉·工业相机·线阵相机
yueyue54314 分钟前
透过现象看本质:以fast_lio架构的整套算法的局部避障改为TEB算法为例深度探讨——如何成为一个合格的算法架构师?
算法·架构
梨花爱跨境14 分钟前
红人视频×A10算法:亚马逊转化率与流量闭环实战
算法
近津薪荼15 分钟前
C++ vector容器底层深度剖析与模拟实现
开发语言·c++
广州山泉婚姻18 分钟前
C++ STL Vector 入门与实战全攻略
c语言·c++