每日一题——Python实现PAT乙级1050 螺旋矩阵(举一反三+思想解读+逐步优化)6千字好文


一个认为一切根源都是“自己不够强”的INTJ

个人主页:用哲学编程-CSDN博客
专栏:每日一题——举一反三
Python编程学习
Python内置函数

Python-3.12.0文档解读

目录

我的写法

时间复杂度分析

空间复杂度分析

总结

我要更强

代码解释

时间复杂度

空间复杂度

总结

哲学和编程思想

哲学思想

编程思想

总结

举一反三

1. 模块化设计

2. 抽象化

3. 迭代与递归

4. 算法优化

5. 数据结构选择

6. 边界条件处理

7. 简约主义

8. 秩序与结构


题目链接:https://pintia.cn/problem-sets/994805260223102976/exam/problems/type/7?problemSetProblemId=994805275146436608&page=0

我的写法

import math# 读取矩阵元素的数量
N = int(input())
# 读取数字列表并按降序排序
nums = list(map(int, input().split()))
nums.sort(reverse=True)def find_dimensions(N):# 找到最接近N的平方根的整数middle = math.isqrt(N)# 从middle开始向上找,直到找到两个数乘积为Nfor i in range(middle, N+1):for j in range(middle, 0, -1):if i * j == N:return i, jdef create_spiral_matrix(N, nums, m, n, seq_paces):# 初始化矩阵matrix = [[0 for i in range(n)] for j in range(m)]index_matrix = [0, -1]  # 矩阵索引初始位置index_nums = 0  # 数字列表索引for i in range(len(seq_paces)):if i % 4 == 0:  # 向右移动seq_paces[i]步index_matrix[1] += 1for j in range(seq_paces[i]):matrix[index_matrix[0]][index_matrix[1] + j] = nums[index_nums]if j == seq_paces[i] - 1:index_matrix[1] = index_matrix[1] + jindex_nums += 1elif i % 4 == 1:  # 向下移动seq_paces[i]步index_matrix[0] += 1for j in range(seq_paces[i]):matrix[index_matrix[0] + j][index_matrix[1]] = nums[index_nums]if j == seq_paces[i] - 1:index_matrix[0] = index_matrix[0] + jindex_nums += 1elif i % 4 == 2:  # 向左移动seq_paces[i]步index_matrix[1] -= 1for j in range(seq_paces[i]):matrix[index_matrix[0]][index_matrix[1] - j] = nums[index_nums]if j == seq_paces[i] - 1:index_matrix[1] = index_matrix[1] - jindex_nums += 1elif i % 4 == 3:  # 向上移动seq_paces[i]步index_matrix[0] -= 1for j in range(seq_paces[i]):matrix[index_matrix[0] - j][index_matrix[1]] = nums[index_nums]if j == seq_paces[i] - 1:index_matrix[0] = index_matrix[0] - jindex_nums += 1return matrixdef calculate_sequence_paces(N, m, n):# 计算螺旋填充的步数序列if m == 1:return [n]elif n == 1:return [1, m - 1]seq_paces = []dif = 0for i in range(N):if i == 0:seq_paces.append(n)dif += 1continueif i % 2 == 1:seq_paces.append(m - dif)elif i % 2 == 0:seq_paces.append(n - dif)dif += 1if seq_paces[-1] == 0:return seq_paces[:-1]return seq_paces# 找到矩阵的维度
m, n = find_dimensions(N)
# 计算螺旋填充的步数序列
seq_paces = calculate_sequence_paces(N, m, n)
# 创建螺旋矩阵
matrix = create_spiral_matrix(N, nums, m, n, seq_paces)
# 输出矩阵
for row in matrix:print(*row)

时间复杂度分析

  • 排序:对 N 个数字进行排序的时间复杂度是 O(N log N)。
  • find_dimensions:这个函数在最坏情况下需要检查大约 sqrt(N) 个可能的行和列组合,因此时间复杂度大约是 O(N)。
  • calculate_sequence_paces:这个函数在最坏情况下需要遍历 N 次,时间复杂度也是 O(N)。
  • create_spiral_matrix:这个函数需要遍历所有步数序列,步数序列的长度大约是 sqrt(N),每次填充矩阵的时间复杂度是 O(N),所以总时间复杂度也是 O(N)。

综合来看,主要的时间消耗来自于排序和矩阵填充,因此总时间复杂度是 O(N log N)。

空间复杂度分析

  • 排序:排序需要的额外空间复杂度是 O(N)。
  • 矩阵:矩阵的大小是 O(N)。
  • 步数序列:步数序列的大小大约是 sqrt(N)。

综合来看,主要的空间消耗来自于矩阵和排序,因此总空间复杂度是 O(N)。

总结

这段代码在功能上实现了将一组数字按螺旋顺序填充到矩阵中,并且在时间和空间复杂度上都是高效的。代码结构清晰,函数职责明确,易于理解和维护。主要的时间消耗来自于排序和矩阵填充,而空间消耗主要由矩阵和排序决定。总体来说,这是一段设计良好且高效的代码。

我要更强

为了解决这个问题,我们需要完成以下步骤:

  1. 读取输入的数字数量 N 和数字列表。
  2. 对数字列表进行降序排序。
  3. 找到满足 m * n = N 且 m >= n 的矩阵维度 m 和 n,并且使得 m - n 最小。
  4. 创建一个空的螺旋矩阵,并按照顺时针方向填充数字。
  5. 输出填充好的螺旋矩阵。

以下是实现上述步骤的Python代码:

import math# 读取输入
N = int(input())
nums = list(map(int, input().split()))# 对数字列表进行降序排序
nums.sort(reverse=True)# 找到合适的矩阵维度
def find_dimensions(N):min_diff = float('inf')m, n = 0, 0for i in range(1, int(math.sqrt(N)) + 1):if N % i == 0:j = N // iif j >= i and j - i < min_diff:min_diff = j - im, n = j, ireturn m, nm, n = find_dimensions(N)# 创建并填充螺旋矩阵
matrix = [[0] * n for _ in range(m)]
top, bottom, left, right = 0, m - 1, 0, n - 1
index = 0while top <= bottom and left <= right:# 向右填充for i in range(left, right + 1):matrix[top][i] = nums[index]index += 1top += 1# 向下填充for i in range(top, bottom + 1):matrix[i][right] = nums[index]index += 1right -= 1# 向左填充if top <= bottom:for i in range(right, left - 1, -1):matrix[bottom][i] = nums[index]index += 1bottom -= 1# 向上填充if left <= right:for i in range(bottom, top - 1, -1):matrix[i][left] = nums[index]index += 1left += 1# 输出螺旋矩阵
for row in matrix:print(' '.join(map(str, row)))

代码解释

  1. 输入读取:首先读取输入的数字数量 N 和数字列表 nums。
  2. 排序:对数字列表 nums 进行降序排序。
  3. 找到矩阵维度:定义 find_dimensions 函数来找到合适的矩阵维度 m 和 n,使得 m * n = N 且 m >= n,并且 m - n 最小。
  4. 填充矩阵:创建一个空的矩阵 matrix,并使用边界指针(top, bottom, left, right)来控制填充方向,按照顺时针方向填充数字。
  5. 输出矩阵:最后,输出填充好的螺旋矩阵。

这个代码在时间和空间复杂度上都是高效的,并且能够正确地解决给定的问题。

代码结构和逻辑

  1. 输入处理:代码首先读取输入的数字数量 N 和数字列表 nums,这一部分的时间复杂度是 O(N),因为需要读取和存储 N 个数字。
  2. 排序:对数字列表 nums 进行降序排序,使用的是 Python 内置的 sort 方法,其时间复杂度是 O(N log N)。
  3. 找到矩阵维度:定义 find_dimensions 函数来找到合适的矩阵维度 m 和 n。这个函数的时间复杂度是 O(sqrt(N)),因为它只需要遍历到 sqrt(N) 的整数。
  4. 填充矩阵:创建一个空的矩阵 matrix,并使用边界指针(top, bottom, left, right)来控制填充方向,按照顺时针方向填充数字。这一部分的时间复杂度是 O(N),因为每个数字只被处理一次。
  5. 输出矩阵:最后,输出填充好的螺旋矩阵。这一部分的时间复杂度也是 O(N),因为需要遍历并输出每个元素。

时间复杂度

综合以上分析,主要的时间消耗来自于排序和矩阵填充。因此,总的时间复杂度是 O(N log N)。

空间复杂度

  1. 输入存储:需要存储 N 个数字,空间复杂度是 O(N)。
  2. 排序:排序过程中需要额外的空间,但由于 Python 的 sort 方法是原地排序,所以这部分的空间复杂度可以忽略不计。
  3. 矩阵存储:需要存储一个 m * n 的矩阵,空间复杂度是 O(N)。

因此,总的空间复杂度是 O(N)。

总结

这段代码在功能上实现了将一组数字按螺旋顺序填充到矩阵中,并且在时间和空间复杂度上都是高效的。代码结构清晰,函数职责明确,易于理解和维护。主要的时间消耗来自于排序和矩阵填充,而空间消耗主要由矩阵和输入数据决定。总体来说,这是一段设计良好且高效的代码。


哲学和编程思想

这段代码体现了多个哲学和编程思想,以下是一些主要的思想:

哲学思想

  1. 秩序与结构:哲学上,秩序和结构是宇宙的基本原则。这段代码通过将无序的数字列表转换为有序的螺旋矩阵,体现了对秩序和结构的追求。
  2. 简约主义:代码尽量保持简洁和高效,避免不必要的复杂性。这种简约主义的思想在代码的结构和逻辑中得到了体现。

编程思想

  1. 模块化:代码被划分为多个函数,每个函数负责一个特定的任务(如输入处理、排序、找到矩阵维度、填充矩阵和输出矩阵)。这种模块化的设计使得代码更易于理解和维护。
  2. 抽象化:通过定义 find_dimensions 函数来抽象出找到矩阵维度的逻辑,使得主逻辑更加简洁。这种抽象化的思想有助于隐藏复杂性,提高代码的可读性。
  3. 迭代与递归:虽然代码中没有显式的递归,但通过边界指针的迭代方式来填充矩阵,体现了迭代思想。迭代是一种逐步推进的解决问题的方法,适用于处理有序数据。
  4. 算法优化:在找到矩阵维度的过程中,代码通过遍历到 sqrt(N) 的整数来减少计算量,体现了算法优化的思想。这种优化减少了不必要的计算,提高了效率。
  5. 数据结构选择:代码选择了列表和二维列表(矩阵)作为主要的数据结构,这种选择是基于问题的需求和数据结构的特性。合理选择数据结构是编程中的重要思想。
  6. 边界条件处理:在填充矩阵的过程中,代码通过边界指针来控制填充方向,并处理边界条件。这种对边界条件的细致处理是编程中的重要思想,有助于避免错误和提高代码的健壮性。

总结

这段代码体现了秩序与结构、简约主义等哲学思想,以及模块化、抽象化、迭代与递归、算法优化、数据结构选择和边界条件处理等编程思想。这些思想的综合运用使得代码既高效又易于理解和维护。


举一反三

结合上述的哲学和编程思想,以下是一些技巧,可以帮助你举一反三,将这些思想应用到其他编程问题中:

1. 模块化设计

  • 技巧:将复杂问题分解为更小的、可管理的部分。每个部分都应该有一个清晰的目的和接口。
  • 应用:在处理大型项目或复杂算法时,尝试将功能分解为独立的函数或类,每个部分负责一个具体的任务。

2. 抽象化

  • 技巧:识别和抽象出问题中的通用模式或逻辑,将其封装为可重用的组件。
  • 应用:在编写代码时,思考哪些部分是通用的,可以被抽象出来,以便在其他地方重用。

3. 迭代与递归

  • 技巧:根据问题的性质选择合适的迭代或递归方法。迭代通常更直观,而递归在处理树状或嵌套结构时更自然。
  • 应用:在解决需要逐步推进或处理层次结构的问题时,考虑使用迭代或递归方法。

4. 算法优化

  • 技巧:始终寻找减少计算量和提高效率的方法。这可能包括使用更高效的数据结构、减少不必要的计算或利用问题的特性。
  • 应用:在设计算法时,思考如何利用问题的特性来优化性能,例如通过预处理、缓存或选择合适的算法策略。

5. 数据结构选择

  • 技巧:根据问题的需求选择合适的数据结构。理解不同数据结构的优缺点,并根据访问模式和操作需求做出选择。
  • 应用:在解决需要频繁查找、插入或删除操作的问题时,考虑使用哈希表、树或链表等数据结构。

6. 边界条件处理

  • 技巧:在编写代码时,始终考虑边界条件和异常情况。确保代码在这些情况下也能正确运行。
  • 应用:在编写循环、递归或处理输入数据时,特别注意边界条件,确保代码的健壮性。

7. 简约主义

  • 技巧:保持代码简洁和清晰。避免过度工程化和不必要的复杂性。
  • 应用:在编写代码时,尽量使用简单直接的解决方案,避免引入不必要的抽象或复杂逻辑。

8. 秩序与结构

  • 技巧:在解决问题时,考虑如何引入秩序和结构,使问题更易于理解和处理。
  • 应用:在处理无序数据或复杂逻辑时,思考如何通过排序、分组或层次化来引入秩序和结构。

通过将这些技巧应用到你的编程实践中,你将能够更有效地解决问题,并提高代码的质量和可维护性。记住,编程不仅仅是编写代码,更是关于如何思考和解决问题。

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

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

相关文章

小区服务前台小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;住户管理&#xff0c;管理员管理&#xff0c;员工管理&#xff0c;安保管理&#xff0c;安保分配管理&#xff0c;客服聊天管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;公告&#xff0c;…

Mongodb集群中的分布式读写

学习mongodb&#xff0c;体会mongodb的每一个使用细节&#xff0c;欢迎阅读威赞的文章。这是威赞发布的第81篇mongodb技术文章&#xff0c;欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题&#xff0c;欢迎在文章下面点个赞&#xff0c;或者关…

Java进阶学习|Day3.Java集合类(容器),Stream的使用,哈希初接触

java集合类&#xff08;容器&#xff09; Java中的集合类主要由Collection和Map这两个接口派生而出&#xff0c;其中Collection接口又派生出三个子接口&#xff0c;分别是Set、List、Queue。所有的Java集合类&#xff0c;都是Set、List、Queue、Map这四个接口的实现类&#xf…

Powershell 简易爬虫,提取种子网站的磁力链接

目录 一. 需求二. 分析2.1 思路分析2.2 技术点 三. 代码四. 效果 一. 需求 ⏹有网站如下所示&#xff0c;先要求从按照关键词搜索到的网页中&#xff0c;提取出所有的磁力链接。 二. 分析 2.1 思路分析 打开网页之后&#xff0c;从网页中先提取出所有的标题相关的url然后再打…

linux驱动部分内容整理

文章目录 Linux驱动概念应用程序调用驱动程序流程驱动模块的加载linux设备号加载和卸载注册新字符设备注册设备节点自动创建设备节点编译编译驱动程序编译应用程序 地址映射ioctrl命令码的解析 并发与竞争原子操作自旋锁信号量互斥体 linux中断DMA映射其它printkmemcpyvolatile…

RocketMQ常用基本操作

文章中的rabbitmq使用的是rocketmq-all-5.1.3-bin-release版本&#xff0c;需要安装包的可自行下载 RockerMQ启动停止命令 启动命令 nohup sh bin/mqnamesrv & nohup sh bin/mqbroker -n localhost:9876 --enable-proxy & 查看日志 tail -f ~/logs/rocketmqlogs/…

明星中药企业系列洞察(九)一手好牌打的稀烂!近500年老字号锁定退市,太安堂为何“塌房”了?

近日&#xff0c;太安堂发布公告称&#xff0c;公司已收到深交所下发的《关于广东太安堂药业股份有限公司股票终止上市的决定》&#xff0c;深交所决定终止公司股票上市&#xff0c;预计其最后交易日期为7月4日。太安堂曾作为国内知名的中成药上市公司之一&#xff0c;是国家级…

matlab仿真 通信信号和系统分析(上)

&#xff08;内容源自详解MATLAB&#xff0f;SIMULINK 通信系统建模与仿真 刘学勇编著第三章内容&#xff0c;有兴趣的读者请阅读原书&#xff09; 一、求离散信号卷积和 主要还是使用卷积函数conv&#xff0c;值得注意的是&#xff0c;得到的卷积和长度结果为81&#xff0…

node.js+uniapp(vue),阿里云短信验证码

reg.vue: 思路是&#xff1a;前端调用获取验证码的接口 > 后端生成验证码返回给前端 > 前端渲染验证码 <template> <div> <input class"sl-input" v-model"phone" type"tel" maxlength"11" placeholder"手…

微信小程序毕业设计-微信食堂线上订餐系统项目开发实战(附源码+论文)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;微信小程序毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计…

【在线评论】不同视角下在线评论对客户满意度和推荐度的影响—推文分析—2024-07-01

今天的推文主题是【在线评论】&#xff0c;重点关注可以关注第四篇&#xff0c;很全面地分析了在线评论的信息多维性。 第一篇从客户的在线评论入手&#xff0c;将客户消费的动机为功利、享受、社会满足&#xff1b;第二篇是关于在线评论对消费者再次选择同一家酒店的机制探索…

MySQL之主从同步、分库分表

1、主从同步的原理 MySQL主从复制的核心是二进制日志 二进制日志&#xff08;binlog&#xff09;记录了所有DDL语句和DML语句&#xff0c;但不包括数据查询&#xff08;select、show&#xff09;语句。 1.1、复制分三步 master主库在事务提交时&#xff0c;会把数据变更记录…

电子战学习笔记01:电子战概论

0、写在文前 本人在学习电子战相关理论知识时&#xff0c;一直感觉无从下手&#xff0c;之后在老师的推荐下购买了《EW101&#xff1a;电子战基础》纸质书籍学习&#xff0c;所以将自己的学习笔记在CSDN上记录一下&#xff0c;也供有需要的同学参考。 1、电子战定义 电子战&…

全网最详细的 gin框架请求数据绑定Bind 源码解析 -- 帮助你全面了解gin框架的请求数据绑定原理和方法

在gin框架中&#xff0c;我们可以将多种请求数据&#xff08;json, form,uri&#xff0c;header等&#xff09;直接绑定到我们定义的结构体&#xff0c;底层是通过反射方式获取我们定义在结构体上面的tag来实现请求数据到我们的结构体数据的绑定的。 在gin的底层有2大体系的数据…

Python pip install模块时C++编译环境问题

pip install模块时C编译环境问题 在接触和使用python后&#xff0c;常常会通过pip install命令安装第三方模块&#xff0c;大多数模块可以直接安装&#xff0c;但许多新同学仍会遇见某些模块需要实时编译后才能安装&#xff0c;如报错信息大概是缺乏C编译环境&#xff0c;本文则…

【Elasticsearch】Elasticsearch索引创建与管理详解

文章目录 &#x1f4d1;引言一、Elasticsearch 索引的基础概念二、创建索引2.1 使用默认设置创建索引2.2 自定义设置创建索引2.3 创建索引并设置映射 三、索引模板3.1 创建索引模板3.2 使用索引模板创建索引 四、管理索引4.1 查看索引4.2 更新索引设置4.3 删除索引 五、索引别名…

Go-知识测试-性能测试

Go-知识测试-性能测试 1. 定义2. 例子3. testing.common 测试基础数据4. testing.TB 接口5. 关键函数5.1 testing.runBenchmarks5.2 testing.B.runN5.3 testing.B.StartTimer5.4 testing.B.StopTimer5.5 testing.B.ResetTimer5.6 testing.B.Run5.7 testing.B.run15.8 testing.B…

监听蓝牙对话的BlueSpy技术复现

本文是之前文章的BlueSpy技术的复现过程&#xff1a;https://mp.weixin.qq.com/s/iCeImLLPAwwKH1avLmqEpA 2个月前&#xff0c;网络安全和情报公司Tarlogic在西班牙安全大会RootedCon 2024上提出了一项利用蓝牙漏洞的BlueSpy技术&#xff0c;并在之后发布了一个名为BlueSpy的概…

git 提交代码忽略eslint代码检测

在暂存代码的时候会出现以上情况因为在提交代码的时候会默认运行代码进行检测&#xff0c;如果不符合代码规范就会进行报错 解决&#xff1a; 使用 git commit --no-verify -m xxx 忽略eslint的检测

Laravel 谨慎使用Storage::append()

在 driver 为 local 时&#xff0c;Storage::append()在高并发下&#xff0c;会存在丢失数据问题&#xff0c;文件被覆写&#xff0c;而非尾部添加&#xff0c;如果明确是本地文件操作&#xff0c;像日志写入&#xff0c;建议使用 Illuminate\Filesystem\Filesystem或者php原生…