六、矩阵问题

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] = 0
                
        for 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, False
        m, n = len(matrix), len(matrix[0])

        for i in range(m):
            if matrix[i][0] == 0:
                is_first_col_zero = True
                break
        for j in range(n):
            if matrix[0][j] == 0:
                is_first_row_zero = True
                break

        for i in range(1, m):
            for j in range(1, n):
                if matrix[i][j] == 0:
                    matrix[i][0] = 0
                    matrix[0][j] = 0

        for i in range(1, m):
            for j in range(1, n):
                if matrix[i][0] == 0 or matrix[0][j] == 0:
                    matrix[i][j] = 0

        if is_first_col_zero:
            for i in range(m):
                matrix[i][0] = 0

        if 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]) - 1
        while True:
            # 在上边界,从最左遍历到最右
            for i in range(left, right+1):
                res.append(matrix[top][i])
            # 重新设置上边界,如果上边界大于下边界,说明遍历完成,下同
            top += 1
            if top > bottom:
                break
            # 在右边界,从最上遍历到最下
            for i in range(top, bottom+1):
                res.append(matrix[i][right])
            right -= 1
            if right < left:
                break
            # 在下边界,从最右遍历到最左
            for i in range(right, left-1, -1):
                res.append(matrix[bottom][i])
            bottom -= 1
            if bottom < top:
                break
            # 在左边界,从最下遍历到最上
            for i in range(bottom, top-1, -1):
                res.append(matrix[i][left])
            left += 1
            if left > right:
                break

        return 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 1
 4 5 6  => 4 5 6  => 8 5 2
 7 8 9     1 2 3     9 6 3

逆时针:

 1 2 3     3 2 1     3 6 9
 4 5 6  => 6 5 4  => 2 5 8
 7 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-1
        while x < m and y >= 0:
            if matrix[x][y] == target:
                return True
            elif matrix[x][y] > target:
                y -= 1
            else:
                x += 1
        return False

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

探索AI视频创新:Sora的奇迹

探索AI视频创新&#xff1a;Sora的奇迹 随着科技的不断演进&#xff0c;AI视频模型已经成为人工智能领域的一颗新星。在这场技术的风暴中&#xff0c;OpenAI的Sora模型以其杰出的性能和前瞻性的技术脱颖而出&#xff0c;正引领着AI视频领域的全新创新浪潮。 Sora的技术之光 …

Net8集成AutoMap

一、概述 使用Net8 搭建WebApi&#xff0c;需要集成AutoMap&#xff0c;方便开发。 二、实现 2.1 安装 AutoMapper 2.2 创建AutoProfile配置类继承Profile namespace AnNeng.Cad.WebApi.Config {using AnNeng.Service.Application.CadAndOss.Dto;using AnNeng.Service.Appl…

BUUCTF---[极客大挑战 2019]BabySQL1

1.这道题和之前做的几道题是相似的&#xff0c;这道题考的知识点更多。难度也比之前的大一些 2.尝试万能密码 or 1#发现过滤了or,使用1和1,发现他对单引号也进行了过滤。于是我尝试进行双写绕过&#xff0c;发现可以通过了。 3.由之前的做题经验可知&#xff0c;这道题会涉及到…

电动车着火事故,敲响梯控安全警钟

文章来源&#xff1a;电动车着火事故&#xff0c;敲响梯控安全警钟_专栏_易百纳技术社区 方案背景&#xff1a; 近年来&#xff0c;电动车起火事故屡有发生。如南京雨花台“223”火灾事故&#xff0c;造成了重大的人员伤亡。还有北京在 2023 年 12 月 28 日发生了一起村民自建…

工业以太网交换机助力电力综合自动化系统卓越运行

随着电力行业不断迈向数字化和自动化时代&#xff0c;电力综合自动化系统逐渐成为实现电网智能化管理的核心。在这一复杂而庞大的系统中&#xff0c;工业以太网交换机扮演着至关重要的角色&#xff0c;连接着各种智能设备&#xff0c;实现数据的快速传输和高效管理&#xff0c;…

共用体union

一、共用体的特性 共用体又叫做联合体&#xff0c;共用体的特性如下&#xff1a; 1.共用体的所有成员共用一段内存空间&#xff0c;且所有成员的起始位置是一致的 2.共用体的值由最后赋值的成员决定 3.共用体的内存大小 共用体的内存必须大于或等于其他成员变量中最大数据类型…

NineData与OceanBase完成产品兼容认证,共筑企业级数据库新生态

近日&#xff0c;云原生智能数据管理平台 NineData 和北京奥星贝斯科技有限公司的 OceanBase 数据库完成产品兼容互认证。经过严格的联合测试&#xff0c;双方软件完全相互兼容、功能完善、整体运行稳定且性能表现优异。 此次 NineData 与 OceanBase 完成产品兼容认证&#xf…

泰迪·上海杉达学院大数据与智能技术工作室挂牌签约仪式圆满结束

2024年3月5日&#xff0c;上海杉达学院邀请广东泰迪智能科技股份有限公司上海分公司总经理彭艳昆一行出席“泰迪上海杉达学院大数据与智能技术工作室”签约挂牌仪式。上海杉达学院副校长兼信息科学与技术学院院长陈瑛、信息科学与技术学院副院长于晓东、信息科学与技术学院党总…

Diffusion Models for Implicit Image Segmentation Ensembles

隐式图像分割集成的扩散模型 摘要 扩散模型在图像生成建模方面表现出令人印象深刻的性能。本文提出了一种新的基于扩散模型的语义分割方法。通过改进训练和采样方案&#xff0c;我们证明了扩散模型可以对医学图像进行病灶分割。为了生成特定于图像的分割&#xff0c;我们在地…

SpringCloud(20)之Skywalking Agent原理剖析

一、Agent原理剖析 使用Skywalking的时候&#xff0c;并没有修改程序中任何一行 Java 代码&#xff0c;这里便使用到了 Java Agent 技术&#xff0c;我 们接下来展开对Java Agent 技术的学习。 1.1 Java Agent Java Agent 是从 JDK1.5 开始引入的&#xff0c;算是一个比较老的…

直播预告|小白开箱: 云数据库在五朵云上的评测

3 月 7 日&#xff0c;周四晚上 19:00-20:30 由明说三人行组织&#xff0c;邀请了 NineData 国际总经理(GM) Ni Demai、云猿生数据 CTO &#xff06; 联合创始人子嘉&#xff0c;和《明说三人行》创始人 &主持人明叔&#xff0c;共同围绕《小白开箱: 云数据库在五朵云上的评…

红帆ioffice-udfGetDocStep.asmx存在SQL注入漏洞

产品简介 红帆iOffice.net从最早满足医院行政办公需求&#xff08;传统OA&#xff09;&#xff0c;到目前融合了卫生主管部门的管理规范和众多行业特色应用&#xff0c;是目前唯一定位于解决医院综合业务管理的软件&#xff0c;是最符合医院行业特点的医院综合业务管理平台&am…

Qt插件之输入法插件的构建和使用(一)

文章目录 输入法概述输入法插件实现及调用输入键盘搭建定义样式自定义按钮实现自定义可拖动标签数字符号键盘候选显示控件滑动控件手绘输入控件输入法概述 常见的输入法有三种形式: 1.系统级输入法 2.普通程序输入法 3.程序自带的输入法 系统级输入法就是咱们通常意义上的输入…

SpringBoot3整合Mybatis-plus报错IllegalArgumentException

错误信息 使用的SpringBoot3版本&#xff1a;3.2.3 java.lang.IllegalArgumentException: Invalid value type for attribute factoryBeanObjectType: java.lang.String 第一想法就是感觉是版本太低导致和SpringBoot3不兼容。 查询mybatis-plus最高的版本 <!-- https://m…

“安康杯”安全知识竞赛活动方案

“安康杯”知识竞赛&#xff0c;顾名思义也就是把竞争机制、奖励机制、激励机制应用于安全生产活动中的群众性“安全”与“健康”竞赛。本次竞赛包括 4 个竞赛环节&#xff0c;分别是胜券在握&#xff08;必答题&#xff09;、 刻不容缓&#xff08;抢答题&#xff09;、披荆斩…

volatile关键字的作用 以及 单例模式(饿汉模式与懒汉模式的区别及改进)

文章目录 &#x1f4a1;volatile保证内存可见性&#x1f4a1;单例模式&#x1f4a1;饿汉模式&#x1f4a1;懒汉模式&#x1f4a1;懒汉模式多线程版&#x1f4a1;volatile防止指令重排序 &#x1f4a1;volatile保证内存可见性 Volatile 修饰的变量能够保证“内存可见性”以及防…

数据库(mysql)-新手笔记(主外键,视图)

主外键 主键(唯一性,非空性) 主键是数据库表中的一个或多个字段&#xff0c;其值唯一标识表中的每一行/记录。 唯一性: 主键字段中的每个值都必须是唯一的&#xff0c;不能有两个或更多的记录具有相同的主键值 非空性&#xff1a;主键字段不能包含NULL值。 外键(引用完整 …

AXI4总线解析

一、读地址 AWVALID和AWREADY同时为高时&#xff0c;在这个上升沿&#xff0c;图中黄线&#xff0c;将接下来的数据写入地址40000000中。 在

递增三元组(第九届蓝桥杯)

文章目录 题目原题链接思路分析二分做法1二分做法2双指针做法前缀和解法 题目 原题链接 递增三元组 思路分析 由时间复杂度可知需要至少优化到 O ( n l o g n ) O(nlogn) O(nlogn)才行 而纯暴力枚举三个数组的话&#xff1a; O ( n 3 ) O(n^3) O(n3) 可以考虑将b[]作为标志&…

28000MB 是多少GB 内存?怎么清理内存空间?

在计算机领域&#xff0c;我们经常会听到关于存储容量的单位&#xff0c;如 MB&#xff08;兆字节&#xff09;和 GB&#xff08;千兆字节&#xff09;。如果您在处理计算机内存或存储空间时遇到了 28000MB 这样的容量&#xff0c;您可能会想知道它相当于多少GB。本文将为您解答…