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

Python算法题集_矩阵置零

 Python算法题集_矩阵置零

  • 题73:矩阵置零
  • 1. 示例说明
  • 2. 题目解析
    • - 题意分解
    • - 优化思路
    • - 测量工具
  • 3. 代码展开
    • 1) 标准求解【三层循环】
    • 2) 改进版一【纵横计数器】
    • 3) 改进版二【原地算法】
  • 4. 最优算法

本文为Python算法题集之一的代码示例

题73:矩阵置零

1. 示例说明

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

示例 1:

img

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

示例 2:

img

输入: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(m*n) 的额外空间,但这并不是一个好的解决方案。
  • 一个简单的改进方案是使用 O(m+n) 的额外空间,但这仍然不是最好的解决方案。
  • 你能想出一个仅使用常量空间的解决方案吗

2. 题目解析

- 题意分解

  1. 原地算法是一个使用辅助的数据结构对输入进行转换的算法。它允许有少量额外的存储空间来储存辅助变量。当算法运行时,输入通常会被输出覆盖。原地算法仅通过替换或交换元素来更新输入序列。不是原地算法有时候称为非原地(not-in-place)或者不得其所(out-of-place)
  2. 本题为将矩阵中的零进行行列填充
  3. 本题的主要计算有2处,1是元素遍历,2是行列填充
  4. 基本的解法是三层循环,读取到任何一个元素为零均进行一次行填充、一次列填充,所以基本的时间算法复杂度为O(n^3)

- 优化思路

  1. 通常优化:减少循环层次

  2. 通常优化:增加分支,减少计算集数量

  3. 通常优化:采用内置算法来提升计算速度

  4. 分析题目特点,分析最优解

    1. 必须对行列进行全扫描以确定所有0,任何一个行/列只要出现一个0就不需要再扫,可以用调度用的数据结构优化

    2. 调度用的数据可以存在输入的矩阵中,实现原地算法【空间复杂度O(1)】


- 测量工具

  • 本地化测试说明:LeetCode网站测试运行时数据波动很大,因此需要本地化测试解决这个问题
  • CheckFuncPerf(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块
  • 本题很难超时,本地化超时测试用例自己生成,详见【最优算法章节】

3. 代码展开

1) 标准求解【三层循环】

三层循环,超过22%在这里插入图片描述

丧心病狂的三层循环,可谓可算尽算,不漏过任何角落,依旧没有超时;看起来超时测试用例还是不给力

import CheckFuncPerf as cfpdef setZeroes_base(matrix):import copymatrixcopy = copy.deepcopy(matrix)ilenrow, ilencol = len(matrix), len(matrix[0])for iIdx in range(ilenrow):for jIdx in range(ilencol):if matrixcopy[iIdx][jIdx] == 0:for kIdx in range(ilenrow):matrix[kIdx][jIdx] = 0for kIdx in range(ilencol):matrix[iIdx][kIdx] = 0import random
matrix = []
for iIdx in range(1000):matrix.append([random.randint(0,1) for x in range(1000)])
result = cfp.getTimeMemoryStr(setZeroes_base, matrix)
print(result['msg'], '执行结果 = {}'.format(result['result']))# 运行结果
函数 setZeroes_base 的运行时间为 62147.93 ms;内存使用量为 336.00 KB 执行结果 = None

2) 改进版一【纵横计数器】

一个横向数组、一个纵向数组,检测需要置零的行列,算法相当于O(n^2) 君临天下,九九归一【超越99%】在这里插入图片描述

import CheckFuncPerf as cfpdef setZeroes_ext1(matrix):ilenrow, ilencol = len(matrix), len(matrix[0])icmdrow, icmdcol = [0] * ilenrow, [0] * ilencolfor iIdx in range(ilenrow):for jIdx in range(ilencol):if matrix[iIdx][jIdx] == 0:icmdrow[iIdx] = 1icmdcol[jIdx] = 1for iIdx in range(ilenrow):if icmdrow[iIdx] > 0:for jIdx in range(ilencol):matrix[iIdx][jIdx] = 0for iIdx in range(ilencol):if icmdcol[iIdx] > 0:for jIdx in range(ilenrow):matrix[jIdx][iIdx] = 0import random
matrix = []
for iIdx in range(1000):matrix.append([random.randint(0,1) for x in range(1000)])
result = cfp.getTimeMemoryStr(setZeroes_ext1, matrix)
print(result['msg'], '执行结果 = {}'.format(result['result']))# 运行结果
函数 setZeroes_ext1 的运行时间为 152.05 ms;内存使用量为 8.00 KB 执行结果 = None

3) 改进版二【原地算法】

在传入的矩阵中保存横向数组、纵向数组,因此空间复杂度为O(1) 表现优异,超过90%在这里插入图片描述

import CheckFuncPerf as cfpdef setZeroes_ext2(matrix):ilenrow, ilencol = len(matrix), len(matrix[0])icmdrow, icmdcol = -1, -1bNotfind = Truefor iIdx in range(ilenrow):for jIdx in range(ilencol):if matrix[iIdx][jIdx] == 0:if bNotfind:icmdrow = iIdxicmdcol = jIdxbNotfind = Falsematrix[icmdrow][jIdx] = 0matrix[iIdx][icmdcol] = 0if bNotfind:returnfor iIdx in range(ilenrow):if iIdx != icmdrow:if matrix[iIdx][icmdcol] == 0:for jIdx in range(ilencol):if jIdx != icmdcol:matrix[iIdx][jIdx] = 0for iIdx in range(ilencol):if iIdx != icmdcol:if matrix[icmdrow][iIdx] == 0:for jIdx in range(ilenrow):if jIdx != icmdrow:matrix[jIdx][iIdx] = 0for iIdx in range(ilenrow):matrix[iIdx][icmdcol] = 0for iIdx in range(ilencol):matrix[icmdrow][iIdx] = 0import random
matrix = []
for iIdx in range(1000):matrix.append([random.randint(0,1) for x in range(1000)])
result = cfp.getTimeMemoryStr(setZeroes_ext2, matrix)
print(result['msg'], '执行结果 = {}'.format(result['result']))# 运行结果
函数 setZeroes_ext2 的运行时间为 508.10 ms;内存使用量为 0.00 KB 执行结果 = None

4. 最优算法

根据本地日志分析,最优算法为第2种setZeroes_ext1

import random
matrix = []
for iIdx in range(1000):matrix.append([random.randint(0,1) for x in range(1000)])# 算法本地速度实测比较
函数 setZeroes_base 的运行时间为 62147.93 ms;内存使用量为 336.00 KB 执行结果 = None
函数 setZeroes_ext1 的运行时间为 152.05 ms;内存使用量为 8.00 KB 执行结果 = None
函数 setZeroes_ext2 的运行时间为 508.10 ms;内存使用量为 0.00 KB 执行结果 = None

一日练,一日功,一日不练十日空

may the odds be ever in your favor ~

相关文章:

  • app对接优量汇收益如何?
  • CSS 控制 video 标签的控制栏组件的显隐
  • 新零售的升维体验,摸索华为云GaussDB如何实现数据赋能
  • 推动海外云手机发展的几个因素
  • jbdc的简单了解
  • 滑动一整屏
  • LeetCode:9.回文数,对整数的反转操作
  • 通过无线打通两个路由器
  • 深入探讨Python中的装饰器技术
  • C语言贪吃蛇详解
  • [软件工具]文档页数统计工具软件pdf统计页数word统计页数ppt统计页数图文打印店快速报价工具
  • Oracle笔记-为表空间新增磁盘(ORA-01691)
  • sklearn模型指标和特征贡献度查看
  • IDEA创建SpringBoot+Mybatis-Plus项目
  • 论文阅读-通过云特征增强的深度学习预测云工作负载转折点
  • 时间复杂度分析经典问题——最大子序列和
  • Angular 2 DI - IoC DI - 1
  • Apache Spark Streaming 使用实例
  • CSS居中完全指南——构建CSS居中决策树
  • CSS魔法堂:Absolute Positioning就这个样
  • FineReport中如何实现自动滚屏效果
  • leetcode讲解--894. All Possible Full Binary Trees
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • PAT A1050
  • React中的“虫洞”——Context
  • SQLServer插入数据
  • Vue--数据传输
  • 计算机在识别图像时“看到”了什么?
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 使用阿里云发布分布式网站,开发时候应该注意什么?
  • 数据结构java版之冒泡排序及优化
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • 用Visual Studio开发以太坊智能合约
  • 在weex里面使用chart图表
  • MyCAT水平分库
  • 国内唯一,阿里云入选全球区块链云服务报告,领先AWS、Google ...
  • 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes ...
  • ​LeetCode解法汇总2304. 网格中的最小路径代价
  • # Swust 12th acm 邀请赛# [ A ] A+B problem [题解]
  • #QT项目实战(天气预报)
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (6)设计一个TimeMap
  • (aiohttp-asyncio-FFmpeg-Docker-SRS)实现异步摄像头转码服务器
  • (二)Eureka服务搭建,服务注册,服务发现
  • (分布式缓存)Redis持久化
  • (七)c52学习之旅-中断
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (十一)手动添加用户和文件的特殊权限
  • (五)大数据实战——使用模板虚拟机实现hadoop集群虚拟机克隆及网络相关配置
  • (转)Linux下编译安装log4cxx
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
  • .NET 材料检测系统崩溃分析
  • .NET/C# 获取一个正在运行的进程的命令行参数
  • .NET/C# 项目如何优雅地设置条件编译符号?
  • .net网站发布-允许更新此预编译站点