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

面试算法13:二维子矩阵的数字之和

题目

输入一个二维矩阵,如何计算给定左上角坐标和右下角坐标的子矩阵的数字之和?对于同一个二维矩阵,计算子矩阵的数字之和的函数可能由于输入不同的坐标而被反复调用多次。例如,输入图2.1中的二维矩阵,以及左上角坐标为(2,1)和右下角坐标为(4,3)的子矩阵,该函数输出8。
在这里插入图片描述

分析

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

只是这个题目提到,对于一个二维矩阵,可能由于输入不同的坐标而反复求不同子矩阵的数字之和,这说明应该优化求和的过程,要尽可能快地实现子矩阵的数字求和。
在这里插入图片描述
阴影面积 = 黄色正方形面积 + 绿色正方行面积 - 红色长方形面积 - 蓝色长方形面积

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

下面分析如何生成辅助矩阵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部分的数字之和。

public class Test {public static void main(String[] args) {int[][] nums = {{3, 0, 1, 4, 2},{5, 6, 3, 2, 1},{1, 2, 0, 1, 5},{4, 1, 0, 1, 7},{1, 0, 3, 0, 5}};sums = generateNumMatrix(nums);int result = sumRegion(2, 1, 4, 3);System.out.println(result);}private static int[][] sums;public static int[][] generateNumMatrix(int[][] matrix) {if (matrix.length == 0 || matrix[0].length == 0) {return null;}int[][] sums = new int[matrix.length + 1][matrix[0].length + 1];for (int i = 0; i < matrix.length; i++) {int rowSum = 0;for (int j = 0; j < matrix[0].length; j++) {rowSum += matrix[i][j];sums[i + 1][j + 1] = sums[i][j + 1] + rowSum;}}return sums;}public static int sumRegion(int row1, int col1, int row2, int col2) {//return sums[row2][col2] + sums[row1-1][col1-1] - sums[row1-1][col2] - sums[row2][col1-1];return sums[row2 + 1][col2 + 1] + sums[row1][col1] - sums[row1][col2 + 1] - sums[row2 + 1][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.lryc.cn/news/177022.html

相关文章:

  • Vue安装插件时候中遇到冲突依赖解决方案
  • realloc函数应用IO泄露体验
  • (c语言)野指针
  • 【Git】轻松学会 Git(一):掌握 Git 的基本操作
  • rust trait对象
  • Linux学习第21天:Linux内核定时器驱动开发: 流淌的时间长河
  • Centos服务在服务器重启后自启
  • 慢性疼痛治疗服务公司Kindly MD申请700万美元纳斯达克IPO上市
  • 代码随想录 Day6 哈希 LeetcodeT454 四数之和II T383赎金信 T15 三数之和 T18 四数之和
  • 干货速来|教你如何撰写毕业论文
  • 【ROS 2】-2 话题通信
  • Unity之NetCode多人网络游戏联机对战教程(2)--简单实现联机
  • makdown文法
  • 新手程序员怎么接单?
  • 接口测试——接口协议抓包分析与mock_L2
  • Seata入门系列【1】安装seata 1.7.1+nacos 2.1.1
  • 2023年职业院校技能大赛中职组----大数据应用与服务赛项任务书试题
  • 产品经理的职业前景怎么样?一文为你全面解答!
  • 【深度学习】图像去噪(2)——常见网络学习
  • 八大排序详解
  • 自定义热加载:如何不停机实现核心代码更新
  • Spring Cloud Alibaba Nacos 2.2.3 (2) - 单机版启动 (winodows 和 linux )
  • VB从资源文件中播放wav音乐文件
  • web:[HCTF 2018]WarmUp
  • 程序开发常用在线工具汇总
  • crypto:丢失的MD5
  • 气传导和骨传导耳机哪个好?气传导耳机好用吗?气传导耳机推荐
  • Spring 的代理开发设计
  • 实现注册手机号用户
  • 【2023年11月第四版教材】第15章《风险管理》(第三部分)