《剑指 Offer》专项突破版 - 面试题 13 : 二维子矩阵的数字之和(C++ 实现)- 二维前缀和

news2024/9/29 11:36:05

题目链接:LCR 013. 二维区域和检索 - 矩阵不可变 - 力扣(LeetCode)

题目

输入一个二维矩阵,如何计算给定左上角坐标和右下角坐标的子矩阵的数字之和?对于同一个二维矩阵,计算子矩阵的数字之和的函数可能由于输入不同的坐标而反复调用多次。

例如,对于下图中的二维矩阵,输入左上角坐标 (2, 1) 和右下角坐标 (4, 3),该函数输出 8(红色框的子矩阵的数字之和);输入左上角坐标 (1, 1) 和右下角坐标 (2, 2),该函数输出 11(绿色框的子矩阵的数字之和);输入左上角坐标 (1, 2) 和右下角坐标 (2, 4),该函数输出 12(蓝色框的子矩阵的数字之和)。

分析

如果不考虑时间复杂度,则采用蛮力法用两个嵌套的循环总是可以求出一个二维矩阵的数字之和。如果矩阵的行数和列数分别是 m 和 n,那么这种蛮力法的时间复杂度是 O(mn)。

只是这个题目提到,对于一个二维矩阵,可能由于输入不同的坐标而反复求不同子矩阵的数字之和,这说明应该优化求和的过程,要尽可能快地实现子矩阵的数字求和。

如果仔细分析子矩阵的数字之和的规律,就可以发现左上角坐标为 (r1, c1)、右下角坐标为 (r2, c2) 的子矩阵的数字之和可以用 4 个左上角坐标为 (0, 0) 的子矩阵的数字之和求得。下图中的阴影部分表示左上角坐标为 (r1, c1)、右下角坐标为 (r2, c2) 的子矩阵。该矩阵的数字之和等于左上角坐标为 (0, 0)、右下角坐标为 (r2, c2) 的子矩阵的数字之和减去左上角坐标为 (0, 0)、右下角坐标为 (r1 - 1, c2) 的子矩阵的数字之和,再减去左上角坐标为 (0, 0)、右下角坐标为 (r2, c1 - 1) 的子矩阵的数字之和,最后加上左上角坐标为 (0, 0)、右下角坐标为 (r1 - 1, c1 - 1) 的子矩阵的数字之和

因此,可以在预处理阶段求出从左上角坐标为 (0, 0) 到每个右下角坐标的子矩阵的数字之和。首先创建一个和输入矩阵大小相同的辅助矩阵 sums,该矩阵中的坐标 (i, j) 的数值为输入矩阵中从左上角坐标 (0, 0) 到右下角坐标 (i, i) 的子矩阵的数字之和

有了这个辅助矩阵 sums,再求左上角坐标为 (r1, c1)、右下角坐标为 (r2, c2) 的子矩阵的数字之和就变得比较容易。该子矩阵的数字之和等于 sums[r2][c2] - sums[r1 - 1][c2] - sums[r2][c1 - 1] + sums[r1 - 1][c1 - 1]

下面分析如何生成辅助矩阵 sums,即求得数组中的每个数字 sums[i][j]。按照生成辅助矩阵 sums 的规则,sums[i][j] 的值等于输入矩阵中从左上角坐标为 (0, 0) 到右下角坐标为 (i, j) 的子矩阵的数字之和。可以把左上角坐标为 (0, 0) 到右下角坐标为 (i, j) 的子矩阵的数字看成由两部分组成。第 1 部分是从左上角坐标为 (0, 0) 到右下角坐标为 (i - 1, j) 的子矩阵,该子矩阵的数字之和等于 sums[i - 1][j]。第 2 部分是输入矩阵中第 i 行中列号从 0 到 j 的所有数字,如果按照从左到右的顺序计算 sums[i][j],则可以逐个累加第 i 行的数字,从而得到子矩阵第 2 部分的数字之和

class NumMatrix {
private:
    vector<vector<int>> sums;
public:
    NumMatrix(vector<vector<int>>& matrix) {
        int m = matrix.size();
        int n = matrix[0].size();
        sums.resize(m + 1, vector<int>(n + 1, 0));
        for (int i = 0; i < m; ++i)
        {
            int rowSum = 0;
            for (int j = 0; j < n; ++j)
            {
                rowSum += matrix[i][j];
                sums[i + 1][j + 1] = sums[i][j + 1] + rowSum;
            }
        }
    }
    
    int sumRegion(int row1, int col1, int row2, int col2) {
        return sums[row2 + 1][col2 + 1] - sums[row1][col2 + 1] - sums[row2 + 1][col1] + sums[row1][col1];
    }
};

注意:如果输入的行数和列数分别是 m 和 n,那么辅助数组 sums 的行数和列数分别为 m + 1 和 n + 1,这样只是为了简化代码逻辑。如果用公式 sums[r2][c2] - sums[r1 - 1][c2] - sums[r2][c1 - 1] + sums[r1 - 1][c1 - 1] 求解左上角坐标为 (r1, c1)、右下角坐标为 (r2, c2) 的子矩阵的数字之和,由于坐标值 r1 或 c1 有可能等于 0,因此 r1 - 1 或 c1 - 1 可能是负数,不再是有效数组的下标。如果在矩阵的最上面增加一行,最左面增加一列,这样就不必担心出现数组下标为 -1 的情形

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1386643.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

rocketmq实现延迟队列思路探讨

大家好&#xff0c;我是了不起&#xff0c;专为小白解决痛点的了不起。 一、非任意时间 1、修改 在服务器端&#xff08;rocketmq-broker端&#xff09;的属性配置文件中加入以下行&#xff1a; messageDelayLevel1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h …

【HarmonyOS4.0】第十一篇-ArkUI布局容器组件(三)

五、格栅布局容器 GridContainer纵向排布栅格布局容器&#xff0c;仅在栅格布局场景中使用。该组件不再维护&#xff0c;推荐使用新组件GridCol、GridRow。 5.1.栅格容器GridRow 栅格容器组件&#xff0c;仅可以和栅格子组件(GridCol)在栅格布局场景中使用。 5.1.1.接口 G…

时光机启动:Spring中如何巧妙实现定时任务?

嗨&#xff0c;亲爱的小伙伴们&#xff01;小米在这里又来和大家分享一些技术干货啦&#xff01;今天我们要探讨的话题是关于Spring框架中如何实现定时任务。对于我们这些热爱技术的小伙伴来说&#xff0c;定时任务可是一个非常有趣而且实用的话题哦&#xff01; 引子 首先&a…

使用emu8086实现——子程序的设计

一、实验目的 学习子程序的结构、特点&#xff0c;以及子程序的设计和调试方法 二、实验内容 1、从字符串中删除一个字符&#xff0c;并存储到寄存器AX中。 代码及注释&#xff1a; data segmentstring db exas ;字符串内容leng dw $-string ; 字符串长度key db x …

js简单原生实现

JavaScript实现 这是一篇用JavaScript技术实现各种效果的学习贴&#xff0c;赋各种代码&#xff0c;供参考&#xff01; 1.按钮事件 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-…

Flink 处理函数(1)—— 基本处理函数

在 Flink 的多层 API中&#xff0c;处理函数是最底层的API&#xff0c;是所有转换算子的一个概括性的表达&#xff0c;可以自定义处理逻辑 在处理函数中&#xff0c;我们直面的就是数据流中最基本的元素&#xff1a;数据事件&#xff08;event&#xff09;、状态&#xff08;st…

Github仓库使用方式

主要参考&#xff1a; 「详细教程」使用git将本地项目上传至Github仓库&#xff08;MacOS为例&#xff09;_github上传代码到仓库-CSDN博客 新建文件夹参考&#xff1a; GitHub使用指南——建立仓库、建立文件夹、上传图片详细教程-CSDN博客 一、新建一个 github 仓库&#…

区块链是怎么存储数据的?

每个块都是有大小限制的新的数据存储单元&#xff0c;当前数据不到上限&#xff0c;那么都可以添加进块。当前数据达到了上限&#xff0c;那么就得分表/分块&#xff0c;超限的那部分数据就需要等待下个区块存储 存储的数据&#xff1a;和mysql一样&#xff0c;文本数据直接存储…

vue3 锚点定位 点击滚动高亮

功能描述 点击导航跳到对应模块的起始位置&#xff0c;并且高亮点击的导航&#xff1b; 滚动到相应的模块时&#xff0c;对应的导航也自动高亮&#xff1b; 效果展示 注意事项 一定要明确哪个是要滚动的盒子&#xff1b;滚动的高度要减去导航栏的高度&#xff1b;当前在导航1…

RFID技术在汽车装备中的应用:提升安全性与效率

RFID技术在汽车装备中的应用&#xff1a;提升安全性与效率 射频识别&#xff08;RFID&#xff09;技术是一种非接触式的自动识别技术&#xff0c;它利用射频信号及其空间耦合和传输特性&#xff0c;实现对目标对象的信息读写。随着汽车工业的不断发展&#xff0c;汽车装备的技…

YOLOv8目标检测中数据集各部分的作用

自学答疑使用&#xff0c;持续更新… 在目标检测任务中&#xff0c;通常将整个数据集划分为训练集&#xff08;training set&#xff09;、验证集&#xff08;validation set&#xff09;和测试集&#xff08;test set&#xff09;。这三个数据集在训练和评估过程中具有不同的…

IT行业——香港优才计划低分段申请之王!

IT行业——香港优才计划低分段申请之王&#xff01; 香港优才计划获批率确实没那么看重分数&#xff0c;看了下2023年的获批案例&#xff0c;一些申请者的基础分数刚过80分&#xff0c;照样顺利获批拿到了香港身份&#xff01; 今天就拿真实数据来分析&#xff0c;盘点那些低分…

JS常用插件 Swiper插件 实现轮播图

Swiper介绍 Swiper 是一款免费以及轻量级的移动设备触控滑块的js框架 中文官网地址: https://www.swiper.com.cn/ 点击查看Swiper演示&#xff0c;里面的功能和样式十分丰富&#xff0c;根据自己的需求选择 中文教程中详细介绍了如何使用Swiper API文档中介绍了各个模块以及参…

gitee完整使用教程,创建项目并上传

目录 一 什么是gitee 二 安装Git 三 登录gitee&#xff0c;生成密钥 四 配置SSH密钥 五 创建项目 六 克隆仓库到本地 七 关联本地工程到远程仓库 八 添加文件 九 异常处理 十 删除仓储 十一 git常用命令 一 什么是gitee gitee是开源中国推出的基于git的代码托管服务…

我成为开源贡献者的原因竟然是做MySql-CDC数据同步

今年下半年机缘巧合下公司决定搭建自己的数据中台&#xff0c;中台的建设势必少不了数据集成。首先面临的就是数据集成技术选型的问题&#xff0c;按照社区活跃度、数据源适配性、同步效率等要求对市面上几个成熟度较高的开源引擎进行了深度调研。 最终经过内部讨论决定用Apac…

智能安全帽识别系统简析

在工业安全领域&#xff0c;安全帽识别系统的重要性不言而喻。这种系统利用先进的图像识别技术&#xff0c;确保工地上每位工人都佩戴安全帽&#xff0c;从而大幅提升工作场所的安全性。本文旨在探讨这一系统的工作原理、应用范围以及面临的挑战。 安全帽识别系统的工作原理 智…

查找算法(部分)

顺序查找 顺序查找是最简单的了&#xff0c;属于无序查找算法&#xff0c;它的原理就是从前往后一个一个的找&#xff0c;如果找到了就返回它的位置&#xff0c;否则就返回-1。 如果有多个相同元素的话&#xff0c;返回第一个该元素的位置。 代码&#xff1a; #include<…

高通开发系列 - RT补丁死机问题scheduling while atomic

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 返回:专栏总目录 目录 背景概述问题现象了解RTOS如何使用高分辨率计时器?RT-mutex 实现设计线程化的中断处理程序睡眠spinlock

图解python | 字符串及操作

1.Python元组 Python的元组与列表类似&#xff0c;不同之处在于元组的元素不能修改。 元组使用小括号&#xff0c;列表使用方括号。 元组创建很简单&#xff0c;只需要在括号中添加元素&#xff0c;并使用逗号隔开即可。 tup1 (ByteDance, ShowMeAI, 1997, 2022) tup2 (1…

通过FTP和HTTPD,搭建内网yum仓库

一、yum仓库的简介 1.yum介绍 yum是一个基于RPM包&#xff08;是Red-Hat Package Manager红帽软件包管理器的缩写&#xff09;构建的软件更新机制&#xff0c;能够自动解决软件包之间的依赖关系。解决了日常工作中的大量查找安装依赖包的时间 为什么会有依赖关系的发生 因为li…