六、矩阵问题

73、矩阵置零(中等)

题目描述

给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。

示例 1:

输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[1,0,1],[0,0,0],[1,0,1]]

示例 2:

输入:matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
输出:[[0,0,0,0],[0,4,5,0],[0,3,1,0]]

提示:

  • m == matrix.length
  • n == matrix[0].length
  • 1 <= m, n <= 200
  • -231 <= matrix[i][j] <= 231 - 1

进阶:

  • 一个直观的解决方案是使用 O(mn) 的额外空间,但这并不是一个好的解决方案。
  • 一个简单的改进方案是使用 O(m + n) 的额外空间,但这仍然不是最好的解决方案。
  • 你能想出一个仅使用常量空间的解决方案吗?

题目思路

对于这道题,要求将一个矩阵中含有0的位置,该行和该列都设置为0。

这道题有点类似于炸弹人的游戏机制,炸弹将一行和一列全部炸裂了。
说到这道题,如果没有空间的限制,很容易实现。

  • 如果是O(mn),非常简单,新开辟一个新的矩阵即可。
  • 如果是O(m+n),也不是很困难,我们利用额外的空间记录对应的行和列是否为0即可。

而如果是常量的空间复杂度,就较为麻烦了,这就需要我们利用现有的空间来记录信息——即使用当前的数组来记录信息。

因此这里,我们的思路是使用当前矩阵的第一行和第一列来记录对应的行和列是否应该为0

不过这里有一个问题:

  • 如果第一行和第一列本身就有0,那么这样的记录就会造成**“污染**”,因此,这里我们需要对第一行和第一列做单独的判断。

在算法流程上:

  • 判断第一行和第一列是否应该为0;
  • (1, 1)开始,自上而下、自左向右判断元素num[i][j]是否为0——如果为0,就设置num[i][0]num[0][j]为0;
  • 再次遍历,根据对应第一行和第一列元素的值,对当前的值进行赋值——如果标记为0,则置为0;
  • 最后,根据第一步的判断结果,对第一行和第一列更新数据;

算法代码

1、O(m+n)

class Solution:def setZeroes(self, matrix: List[List[int]]) -> None:"""Do not return anything, modify matrix in-place instead."""zero_row, zero_col = [], []m, n = len(matrix), len(matrix[0])for i in range(m):for j in range(n):if matrix[i][j] == 0:zero_row.append(i)zero_col.append(j)for r in zero_row:for j in range(n):matrix[r][j] = 0for c in zero_col:for i in range(m):matrix[i][c] = 0

2、常量空间

class Solution:def setZeroes(self, matrix: List[List[int]]) -> None:"""Do not return anything, modify matrix in-place instead."""is_first_row_zero, is_first_col_zero = False, Falsem, n = len(matrix), len(matrix[0])for i in range(m):if matrix[i][0] == 0:is_first_col_zero = Truebreakfor j in range(n):if matrix[0][j] == 0:is_first_row_zero = Truebreakfor i in range(1, m):for j in range(1, n):if matrix[i][j] == 0:matrix[i][0] = 0matrix[0][j] = 0for i in range(1, m):for j in range(1, n):if matrix[i][0] == 0 or matrix[0][j] == 0:matrix[i][j] = 0if is_first_col_zero:for i in range(m):matrix[i][0] = 0if is_first_row_zero:for j in range(n):matrix[0][j] = 0

54、螺旋矩阵(中等)

题目描述

给你一个 mn 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

示例 1:

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

示例 2:

输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 10
  • -100 <= matrix[i][j] <= 100

题目思路

对于这道题,要求我们按照顺时针的方向对矩阵进行遍历,最后转化为一维数组。
在进行数组展开时,我们可以看到顺序是:

  • 向右->向下->向左->向上

如果直接去模拟,整个过程较为繁琐,需要定义每个方向要走多少步等。
这里,我们通过不断重新定义矩阵上下左右边界的方法,来实现循环遍历。

算法具体步骤:

  • 初始化矩阵的上下左右边界;
  • 在上边界(即第一行)从最左移动到最右,此时第一行遍历完后相当于已经用过了,因此可以直接从图中删去,即重新定义上边界(top+1);
    • 若重新定义上边界后,上、下边界交错(top > bottom),说明此时矩阵遍历结束,直接跳出循环,返回结果即可;
    • 若上下不交错,则继续在最右边界处,从最上遍历到最下,逻辑同理;
  • 不断循环上述步骤,直到其中某两条边界交错,跳出循环,返回结果;

算法代码

class Solution:def spiralOrder(self, matrix: List[List[int]]) -> List[int]:res = []# 定义矩阵上下边界top, bottom = 0, len(matrix) - 1# 定义矩阵左右边界left, right = 0, len(matrix[0]) - 1while True:# 在上边界,从最左遍历到最右for i in range(left, right+1):res.append(matrix[top][i])# 重新设置上边界,如果上边界大于下边界,说明遍历完成,下同top += 1if top > bottom:break# 在右边界,从最上遍历到最下for i in range(top, bottom+1):res.append(matrix[i][right])right -= 1if right < left:break# 在下边界,从最右遍历到最左for i in range(right, left-1, -1):res.append(matrix[bottom][i])bottom -= 1if bottom < top:break# 在左边界,从最下遍历到最上for i in range(bottom, top-1, -1):res.append(matrix[i][left])left += 1if left > right:breakreturn res

48、旋转图像(中等)

题目描述

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

示例 1:

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

示例 2:

输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]

提示:

  • n == matrix.length == matrix[i].length
  • 1 <= n <= 20
  • -1000 <= matrix[i][j] <= 1000

题目思路

对于这道题,本质上是要求我们将一个二维n*n矩阵顺时针旋转90度。

如果我们可以使用额外空间,比较简单直接:

  • 对于矩阵中第i行第j个元素,旋转后,会出现在倒数第i列的第j个位置:
    • matrix_new[j][n - i - 1] = matrix[i][j]

但题目这里不允许使用额外的空间,因此这里我们需要在原二维矩阵进行操作,这里可以直接通过翻转得到。

  • 顺时针旋转:
    • 先通过水平轴翻转,再根据主对角线翻转;
  • 逆时针旋转:
    • 先通过垂直轴翻转, 再根据主对角线旋转;

顺时针:

 1 2 3     7 8 9     7 4 14 5 6  => 4 5 6  => 8 5 27 8 9     1 2 3     9 6 3

逆时针:

 1 2 3     3 2 1     3 6 94 5 6  => 6 5 4  => 2 5 87 8 9     9 8 7     1 4 7

以顺时针为例,之所以能够通过两次翻转得到,是由于:
1、水平轴翻转:

  • matrix[row][col] => matrix[n-row-1][col]

2、主对角线翻转:

  • matrix[n-row-1][col] => matrix[col][n-row-1]

因此最终可以得到:

  • matrix_new[j][n - i - 1] = matrix[i][j]

算法代码

class Solution:def rotate(self, matrix: List[List[int]]) -> None:"""Do not return anything, modify matrix in-place instead."""matrix.reverse()for i in range(len(matrix)):for j in range(i+1, len(matrix)):matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]

附带逆时针:

class Solution48:def rotate(self, matrix: List[List[int]]) -> None:"""Do not return anything, modify matrix in-place instead."""matrix = [list(reversed(x)) for x in matrix]for i in range(len(matrix)):for j in range(i+1, len(matrix)):matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]

240、搜索二维矩阵 II(中等)

题目描述

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:

  • 每行的元素从左到右升序排列。
  • 每列的元素从上到下升序排列。

示例 1:

输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
输出:true

示例 2:

输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 20
输出:false

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= n, m <= 300
  • -109 <= matrix[i][j] <= 109
  • 每行的所有元素从左到右升序排列
  • 每列的所有元素从上到下升序排列
  • -109 <= target <= 109

题目思路

对于这道题,要求我们在一个二维数组中找到目标值。

首先,我们可以直接使用暴力搜索的

不过在这道题中该二维数组具备:

  • 每行的元素从左到右升序排列;
  • 每列的元素从上到下升序排列;

因此,我们可以从矩阵的右上角(0, n-1)进行从右向左、从上到下进行查找。

这是由于如果我们从左上角开始,如果matrix[x][y]小于target,那么下一个查找的数字既有可能在右边、也有可能在下边,查找起来就很麻烦。

然而如果我们从右上角开始查找:

  • 如果matrix[x][y] == target,说明查找完成;
  • 如果matrix[x][y] > target,由于每一列的元素都是升序排列的,那么在当前的搜索矩阵中,所有位于第 y 列的元素都是严格大于 target 的,因此我们可以将它们全部忽略,即将 y-1
  • 如果matrix[x][y] < target,由于每一行的元素都是升序排列的,那么在当前的搜索矩阵中,所有位于第 x 行的元素都是严格小于 target 的,因此我们可以将它们全部忽略,即将 x+1

在搜索的过程中,如果我们超出了矩阵的边界,那么说明矩阵中不存在 target

算法代码

class Solution:def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:m, n = len(matrix), len(matrix[0])x, y = 0, n-1while x < m and y >= 0:if matrix[x][y] == target:return Trueelif matrix[x][y] > target:y -= 1else:x += 1return False

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用query请求数据出现500的报错

我在写项目的时候遇到了一个问题&#xff0c;就是在存商品id的时候我将它使用了JSON.stringify的格式转换了&#xff01;&#xff01;&#xff01;于是便爆出了500这个错误&#xff01;&#xff01;&#xff01; 我将JSON.stringify的格式去除之后&#xff0c;它就正常显示了&…

可视化管理的kanban插件 | Obsidian实践

继上一篇文章之后&#xff0c;有朋友提问说&#xff1a; 刚好&#xff0c;关于kanban插件的素材&#xff0c;是之前一早就准备好的&#xff0c;便快速整理成文&#xff0c;简单分享一下个人实践。 Prompt&#xff1a;项目流程管理看板&#xff0c;色彩鲜艳。by 通义万象 看板管…

计算机网络-第2章 物理层

本章内容&#xff1a;物理层和数据通信的概念、传输媒体特点&#xff08;不属于物理层&#xff09;、信道复用、数字传输系统、宽带接入 2.1-2.2 物理层和数据通信的概念 物理层解决的问题&#xff1a;如何在传输媒体上传输数据比特流&#xff0c;屏蔽掉传输媒体和通信手段的差…

pywin32,一个超强的 Python 库!

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个超强的 Python 库 - pywin32。 Github地址&#xff1a;https://github.com/mhammond/pywin32 在Python的世界里&#xff0c;有许多优秀的第三方库可以帮助开发者更轻松地处理各种任务。其中&a…

前端 JS 经典:Content-type 详解

1. 什么是 Content-Type Content-Type 是 HTTP 协议中的一个请求头或响应头字段&#xff0c;用于指示发送或接收的实体的媒体类型&#xff0c;告诉服务器或客户端如何解析和处理请求或响应的主体部分。 2. Content-Type 的构成 Content-Type 由两部分组成&#xff1a;媒体类型…

十五 超级数据查看器 讲解稿 外观设置

十五 超级数据查看器 讲解稿 外观设置 视频讲座地址 讲解稿全文: 大家好&#xff0c;今天讲解超级数据查看器,详情界面的外观设置。 首先&#xff0c;我们打开超级数据查看器。 本节课以成语词典为例来做讲述。 我们打开成语词典这个表&#xff0c;随便选一条记录点击&#x…

Flink 定义 Temporal Table 的两种方式:Temporal Table DDL 和 Temporal Table Function

博主历时三年精心创作的《大数据平台架构与原型实现&#xff1a;数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行&#xff0c;点击《重磅推荐&#xff1a;建大数据平台太难了&#xff01;给我发个工程原型吧&#xff01;》了解图书详情&#xff0c;…

20240301基于机器学习的低热导率多孔石墨烯设计

Name&#xff1a; Machine learning-based design of porous graphene with low thermal conductivity DOI&#xff1a; https://doi.org/10.1016/j.carbon.2019.10.037 总结&#xff1a;所有库训练CNN&#xff0c;证明可行&#xff0c;然后对同孔隙率结构&#xff0c;进行迭代…

整理的一些脑模板及节点的名称

整理的一些脑模板及节点的名称 前言模板简介AAL90模板HOA112 模板 前言 自己看论文找的&#xff0c;因为有些数据集网站的确有点难找到模板的名称等等。所以主要是看一些论文&#xff0c;因为有文献&#xff0c;所以更有保障一些。当然也有一些在数据网站上比较容易找到所以一…

挑战杯 基于深度学习的中文情感分类 - 卷积神经网络 情感分类 情感分析 情感识别 评论情感分类

文章目录 1 前言2 情感文本分类2.1 参考论文2.2 输入层2.3 第一层卷积层&#xff1a;2.4 池化层&#xff1a;2.5 全连接softmax层&#xff1a;2.6 训练方案 3 实现3.1 sentence部分3.2 filters部分3.3 featuremaps部分3.4 1max部分3.5 concat1max部分3.6 关键代码 4 实现效果4.…

2024.3.1

机械臂 #include<myhead.h> #define SER_IP "172.20.10.5" //服务器ip #define SER_PORT 8888 //服务器端口号 #define CLI_IP "192.168.111.154" //客户端IP #define CLI_PORT 9999 //客户端端口号int main(int argc, const char *argv[]) {int c…

Qt/事件分发器/事件过滤器

事件分发器 //事件分发器bool event(QEvent* e); //事件分发器&#xff1a;&#xff1a;用途 分发事件 bool MyLabel::event(QEvent* e) {if(e->type() QEvent::MouseButtonPress){//如果是鼠标摁下 拦截事件 不向下分发QMouseEvent* ev static_cast<QMouseEvent*>…