每日一题——Python实现PAT甲级1042 Shuffling Machine(举一反三+思想解读+逐步优化)


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

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

Python-3.12.0文档解读

目录

我的写法

功能分析

时间复杂度

空间复杂度

总结

代码点评

我要更强

优化方向

优化后的代码

优化分析

代码点评

哲学和编程思想

1. 空间-时间权衡(Space-Time Tradeoff)

2. 内存重用(Memory Reuse)

3. 最小化副作用(Minimize Side Effects)

4. 简洁性(Simplicity)

5. 局部性原理(Principle of Locality)

6. KISS 原则(Keep It Simple, Stupid)

7. DRY 原则(Don't Repeat Yourself)

举一反三

1. 空间-时间权衡(Space-Time Tradeoff)

技巧:

示例:

2. 内存重用(Memory Reuse)

技巧:

示例:

3. 最小化副作用(Minimize Side Effects)

技巧:

示例:

4. 简洁性(Simplicity)

技巧:

示例:

5. 局部性原理(Principle of Locality)

技巧:

示例:

6. KISS 原则(Keep It Simple, Stupid)

技巧:

示例:

7. DRY 原则(Don't Repeat Yourself)

技巧:

示例:

总结


 题目链接
 


我的写法

K = int(input())  # 读取输入的K值,表示需要进行洗牌的次数
orders = list(map(int, input().split()))  # 读取输入的顺序列表,表示洗牌后的顺序# 初始化一副扑克牌
init_cards = []
init_cards += ['S' + str(i + 1) for i in range(13)]  # 添加黑桃(S)1到13
init_cards += ['H' + str(i + 1) for i in range(13)]  # 添加红桃(H)1到13
init_cards += ['C' + str(i + 1) for i in range(13)]  # 添加梅花(C)1到13
init_cards += ['D' + str(i + 1) for i in range(13)]  # 添加方块(D)1到13
init_cards.append('J1')  # 添加小王(J1)
init_cards.append('J2')  # 添加大王(J2)outputs = []  # 初始化输出列表for i in range(K):  # 进行K次洗牌outputs = [''] * 54  # 每次洗牌后创建一个空的输出列表for j in range(54):  # 遍历每一张牌outputs[orders[j] - 1] = init_cards[j]  # 根据orders中的顺序将init_cards中的牌放到对应位置init_cards = outputs  # 更新init_cards为新排列的牌,准备进行下一次洗牌print(*outputs)  # 打印最终结果,将输出列表中的牌以空格分隔


 

这段代码是一个模拟扑克牌洗牌过程的程序,详细分析如下:

功能分析

这段代码的功能是根据用户输入的顺序 orders 和洗牌次数 K 模拟扑克牌的洗牌过程。输入顺序 orders 是一个包含 54 个整数的列表,表示每张牌在洗牌之后的新位置。程序按照这个顺序对扑克牌进行 K 次洗牌,并最终输出洗牌后的扑克牌顺序。

时间复杂度

  1. 初始化扑克牌:
    • 使用列表推导式初始化扑克牌,时间复杂度为 (O(1)),因为这是固定的 54 张牌。
  2. 洗牌过程:
  • 外层循环执行 (K) 次,其中 (K) 是输入的洗牌次数。
  • 内层循环执行 54 次,处理每一张牌的移动。
  • 整体的时间复杂度为 (O(K \times 54)),即 (O(54K))。通常情况下 (O(54K)) 可以简化为 (O(K)),因为 54 是一个常数。

空间复杂度

  1. 固定空间:
    • init_cards 和 outputs 各有 54 个元素,空间复杂度为 (O(54)),即 (O(1)),因为 54 是常数。
    • 其它变量如 K 和 orders(长度为 54)也是常量级别的空间开销。
  2. 洗牌过程:
  • 在每次洗牌中,新的 outputs 列表会覆盖旧的 init_cards 列表,但总的占用空间仍然是两个 54 元素的列表,空间复杂度为 (O(54 \times 2)),即 (O(108))。但这仍然是常数级别,简化为 (O(1))。

总结

  • 时间复杂度: (O(K))
  • 空间复杂度: (O(1))

代码点评

  1. 代码结构清晰:初始化扑克牌,循环 K 次洗牌,最后输出结果,逻辑非常清晰。
  2. 注释明确:每步操作都有详细注释,便于理解。
  3. 效率合理:时间复杂度和空间复杂度都很低,适用于大多数实际应用场景。
  4. 可扩展性:如果扑克牌数目或洗牌规则发生变化,代码也易于修改和扩展。

总体来说,这段代码简洁高效,符合专业编程规范。


我要更强

优化这段代码的时间复杂度和空间复杂度并不容易,因为洗牌过程本身需要对每张牌进行重新排列。然而,可以通过减少不必要的内存分配和复制来优化空间使用。以下是几个可能的优化方向:

优化方向

  1. 内存优化:避免在每次洗牌时创建新的列表,而是使用额外的空间来保存当前和下一步的状态。
  2. 减少复制操作:尽量减少对列表的整体复制操作。

优化后的代码

通过优化空间使用,我们可以改进代码的内存效率。以下是优化后的代码:

K = int(input())  # 读取输入的K值,表示需要进行洗牌的次数
orders = list(map(int, input().split()))  # 读取输入的顺序列表,表示洗牌后的顺序# 初始化一副扑克牌
init_cards = []
init_cards += ['S' + str(i + 1) for i in range(13)]  # 添加黑桃(S)1到13
init_cards += ['H' + str(i + 1) for i in range(13)]  # 添加红桃(H)1到13
init_cards += ['C' + str(i + 1) for i in range(13)]  # 添加梅花(C)1到13
init_cards += ['D' + str(i + 1) for i in range(13)]  # 添加方块(D)1到13
init_cards.append('J1')  # 添加小王(J1)
init_cards.append('J2')  # 添加大王(J2)current = init_cards[:]  # 当前牌组初始化为init_cards的复制
next_cards = [''] * 54  # 初始化一个空的牌组用于保存下一步结果for i in range(K):  # 进行K次洗牌for j in range(54):  # 遍历每一张牌next_cards[orders[j] - 1] = current[j]  # 根据orders中的顺序将current中的牌放到对应位置current, next_cards = next_cards, current  # 交换current和next_cards,准备进行下一次洗牌print(*current)  # 打印最终结果,将current牌组中的牌以空格分隔

优化分析

  1. 时间复杂度:
    • 外层循环执行 (K) 次,其中 (K) 是输入的洗牌次数。
    • 内层循环执行 54 次,处理每一张牌的移动。
    • 时间复杂度仍为 (O(K \times 54)),即 (O(K)),因为 54 是常数。
  2. 空间复杂度:
  • 使用了两个固定大小的列表 current 和 next_cards,每个列表包含 54 个元素。
  • 总的空间复杂度还是 (O(54 \times 2)),即 (O(1)),因为 54 是常数。

代码点评

  • 内存优化:新代码避免了重复分配和复制列表,通过交换引用来保存洗牌结果。
  • 逻辑清晰:洗牌过程的逻辑保持不变,代码结构仍然清晰易懂。
  • 效率提升:减少了内存分配和复制操作,提高了内存使用效率。

总的来说,这段优化后的代码在保留了原有逻辑的基础上优化了内存使用,更加高效。


哲学和编程思想

优化代码不仅仅是一个技术问题,也涉及到一些哲学和编程思想。这些思想可以帮助我们更好地理解为什么进行某些优化,以及如何进行有效的优化。以下是这段代码优化涉及到的主要哲学和编程思想:

1. 空间-时间权衡(Space-Time Tradeoff)

  • 哲学:在计算中,有时我们可以用更多的空间来换取更少的时间,反之亦然。这种权衡是许多优化决策的核心。
  • 应用:在这段代码中,通过使用两个固定大小的列表(current 和 next_cards),我们避免了每次洗牌都创建新的列表,从而节省了时间。

2. 内存重用(Memory Reuse)

  • 哲学:重用现有的资源而不是频繁分配和释放资源,可以提高效率和性能。
  • 应用:我们通过交换 current 和 next_cards 的引用来重用内存,而不是每次都创建新的列表。这减少了内存分配的开销,提高了性能。

3. 最小化副作用(Minimize Side Effects)

  • 哲学:减少函数或过程对外部状态的影响,有助于提高代码的可维护性和可预测性。
  • 应用:通过交换引用而不是复制列表,我们有效地将副作用限制在局部变量内部。这使得代码更容易理解和维护。

4. 简洁性(Simplicity)

  • 哲学:简洁的代码通常更容易理解、维护和调试。复杂性应尽可能地被消除。
  • 应用:代码结构清晰,逻辑明确,没有不必要的操作,保持了代码的简洁性。

5. 局部性原理(Principle of Locality)

  • 哲学:程序应尽量在局部范围内操作数据,以提高缓存效率和性能。
  • 应用:通过使用固定大小的列表,我们确保操作是局部的,数据在内存中的位置相对固定,从而提高了缓存命中率。

6. KISS 原则(Keep It Simple, Stupid)

  • 哲学:代码应保持尽可能简单,不引入不必要的复杂性。
  • 应用:通过简单地交换列表的引用,而不是复杂的复制和分配操作,我们遵循了 KISS 原则。

7. DRY 原则(Don't Repeat Yourself)

  • 哲学:尽量避免代码重复,提取公共逻辑到单一的地方。

应用:在优化过程中,避免了重复分配和复制列表的操作,集中在一个简单的引用交换上。


举一反三

理解并应用这些哲学和编程思想可以帮助你在编程中举一反三,开发出更高效、可维护的代码。以下是一些技巧和建议,结合之前提到的哲学和编程思想,帮助你在实际编程中应用:

1. 空间-时间权衡(Space-Time Tradeoff)

技巧:
  • 缓存计算结果:如果一个函数的计算结果会被多次使用,可以缓存结果以减少重复计算。
  • 预处理数据:在数据处理前进行一些预处理,可能会增加一些空间开销,但可以显著减少后续处理时间。
示例:

def fibonacci(n, memo={}):if n in memo:return memo[n]if n <= 1:return nmemo[n] = fibonacci(n-1, memo) + fibonacci(n-2, memo)return memo[n]

2. 内存重用(Memory Reuse)

技巧:
  • 池化对象:复用对象而不是频繁地创建和销毁它们,比如使用对象池。
  • 就地修改:当安全和可行时,尽量就地修改数据而不是创建新的副本。
示例:

def in_place_reverse(arr):left, right = 0, len(arr) - 1while left < right:arr[left], arr[right] = arr[right], arr[left]left += 1right -= 1

3. 最小化副作用(Minimize Side Effects)

技巧:
  • 函数式编程:尽量编写纯函数(无副作用),避免修改全局状态。
  • 局部变量:使用局部变量而不是全局变量或类变量来保存临时状态。
示例:

def pure_function(x, y):return x + y

4. 简洁性(Simplicity)

技巧:
  • 拆分函数:将复杂的函数拆分成多个小函数,每个函数只做一件事。
  • 清晰命名:使用清晰、描述性的变量和函数名称,便于理解代码意图。
示例:

def process_data(data):clean_data = clean(data)transformed_data = transform(clean_data)return transformed_datadef clean(data):# 清理数据passdef transform(data):# 转换数据pass

5. 局部性原理(Principle of Locality)

技巧:
  • 数据局部性:尽量让相关的数据在内存中存放在一起,减少缓存未命中。
  • 代码局部性:尽量在一个局部范围内完成相关操作,减少跨模块调用。
示例:

def sum_of_squares(arr):return sum(x * x for x in arr)

6. KISS 原则(Keep It Simple, Stupid)

技巧:
  • 避免过度优化:在没有明确性能问题时,不要过早进行复杂的优化。
  • 直观实现:优先选择直观、简单的实现方法,复杂的方法留作备选。
示例:

def calculate_area(radius):return 3.14 * radius * radius  # 简单计算圆的面积

7. DRY 原则(Don't Repeat Yourself)

技巧:
  • 抽取公共代码:将重复出现的代码抽取到一个独立函数或模块中。
  • 使用参数化:通过参数化来减少代码重复,增强代码的灵活性。
示例:

def calculate(operation, x, y):if operation == 'add':return x + yelif operation == 'subtract':return x - y# 更多操作...

总结

通过理解和应用这些哲学和编程思想,可以帮助在编程中实现以下目标:

  • 优化性能:通过合理的空间-时间权衡和内存重用,改进代码效率。
  • 提高可维护性:通过最小化副作用、保持代码简洁和避免重复,增强代码的可读性和可维护性。
  • 提高代码局部性:通过遵循局部性原理,改进代码运行效率和可预测性。

记住,这些技巧和思想不是独立的,而是相互关联和互补的。理解和实践这些思想不仅能提高你的编程能力,还能写出更加优雅和高效的代码。


感谢。

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

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

相关文章

stm32F4的时钟树

时钟其实就是单片机的心脏。首先我们的高速外部时钟&#xff08;HES&#xff09;&#xff0c;看名字就可知道外部高速时钟是由外部所提供的其是高速的&#xff0c;其具体可以是有源晶振或者无源晶振所提供的时钟。而在时钟树图中我们从OSC_IN、OSC_OUT进入&#xff0c;然后经过…

【项目管理知识】项目质量管理措施

1、持续改进&#xff08;PDCA&#xff09; 戴明循环或称PDCA循环、PDSA循环。戴明循环的研究起源于20世纪20年代&#xff0c;先是有着“统计质量控制之父”之称的著名的统计学家沃特阿曼德休哈特&#xff08;Walter A. Shewhart&#xff09;在当时引入了“计划-执行-检查&…

低代码平台:教育机构数字化转型的技术新引擎

在数字化浪潮汹涌而来的今天&#xff0c;教育行业正迎来前所未有的变革。随着技术的不断进步和教育理念的更新&#xff0c;越来越多的教育机构开始意识到数字化转型的重要性。而在这场转型的浪潮中&#xff0c;低代码平台以其独特的优势&#xff0c;正成为教育机构实现数字化转…

7-13 字节解析(parse_byte)--PTA实验C++

一、题目描述 字节有几位都没个标准&#xff0c;古代程序员过的什么日子啊&#xff1f;还好现在字节统一成8位了。 鉴于我对C已有相当牢固的基础&#xff0c;可以探索底层开发了&#xff0c;先做个解析十六进制字节数据的功能吧。 输入规格 每项待读入的字节数据由两个非空白…

virtualbox识别windows上usb设备

当你插入 USB 时&#xff0c;你的宿主操作系统可以轻松访问它并使用其中的文件。如果需要VirtualBox 的虚拟机也能访问物理机的 USB设备&#xff0c;需要安装安装扩展包管理器。 第一步&#xff1a; 要安装 VirtualBox 扩展包&#xff0c;只需访问 VirtualBox 官方下载页面&a…

骨传导耳机哪一款比较值得入手?年度精选好用骨传导耳机推荐

现在很多年轻人都会选择用骨传导耳机&#xff0c;因为骨传导耳机更加方便&#xff0c;不用入耳&#xff0c;不会伤害到耳朵&#xff0c;对耳膜也没有什么伤害。同时&#xff0c;因为骨传导耳机的结构也比较简单&#xff0c;所以佩戴也会更加舒适。接下来就给大家推荐几款口碑不…

LabVIEW老程序功能升级:重写还是改进?

概述&#xff1a;面对LabVIEW老程序的功能升级&#xff0c;开发者常常面临重写与改进之间的选择。本文从多个角度分析两种方法的利弊&#xff0c;并提供评估方法和解决思路。 重写&#xff08;重新开发&#xff09;的优势和劣势&#xff1a; 优势&#xff1a; 代码清晰度高&a…

面试二十七、 CAS和Atomic

CAS锁机制&#xff08;无锁、自旋锁、乐观锁、轻量级锁&#xff09;-CSDN博客 1. ABA问题 在C中&#xff0c;可以使用std::atomic和版本号来解决ABA问题。C标准库没有直接提供类似Java的AtomicStampedReference&#xff0c;但可以通过将版本号和指针组合在一起实现类似的效果。…

ESP32-C3模组上跑通OTA升级(10)

接前一篇文章&#xff1a;ESP32-C3模组上跑通OTA升级&#xff08;9&#xff09; 八、程序调试过程中遇到的问题及解决 前边各篇文章主要讲解了OTA的基础知识以及示例代码&#xff0c;但这其实是&#xff08;远远&#xff09;不够的&#xff0c;真正要在ESP32-C3芯片上跑通&…

【并发程序设计】13.信号机制

13.信号机制 概念&#xff1a; 信号机制是Unix、类Unix以及其他POSIX兼容的操作系统中的一种进程间通讯方式&#xff0c;它允许进程在发生特定事件时接收通知。 信号机制是操作系统中的一个重要概念&#xff0c;它提供了一种异步的通知机制&#xff0c;用于在进程之间传递消…

【Python】解决Python报错:IndexError: queue index out of range

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

【Unity Shader入门精要 第12章】屏幕后处理效果(二)

1. 卷积 在图像处理中&#xff0c;卷积操作就是使用一个卷积核对一张图像中的每个像素做一系列的操作。 卷积核通常是一个四方形网格结构&#xff0c;如2x2、3x3的方形区域&#xff0c;该区域内每个方格都有一个权重值。 当对图像中的某个像素进行卷积操作时&#xff0c;将卷…

Linux域名解析不了/网络不可达/虚拟机连接不了的问题

记录域名解析不了/网络不可达/虚拟机连接不了的问题问题 目录 文章目录 记录域名解析不了/网络不可达/虚拟机连接不了的问题问题1.首先确定已经连接上路由器(我的就是在这嗝屁了....)1.1 查看路由表1.2查看当前的网络连接状态&#xff0c;包括网关1.3查看网络接口的状态&…

如何解决研发数据传输层面安全可控、可追溯的共性需求?

研发数据在企业内部跨网文件交换&#xff0c;是相对较为普遍而频繁的文件流转需求&#xff0c;基于国家法律法规要求及自身安全管理需要&#xff0c;许多企业进行内部网络隔离。不同企业隔离方案各不相同&#xff0c;比如银行内部将网络隔离为生产网、办公网、DMZ区&#xff0c…

十四天学会Vue——Vue核心下篇(理论+实战)(第三天)

一、Vue核心下篇 1.15 常用的内置指令 1. v-text <!--准备好一个容器 --><div id"root"><!-- 1.v-text中的字符替换掉div整个字符 --><div v-text"name">你好,{{name}}</div><!-- 2.将标签当做字符串解析 --><di…

网络原理-TCP/IP --应用层

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 今天你敲代码了吗 目录 3.网络原理 -TCP/IP3.1 应用层 3.网络原理 -TCP/IP 3.1 应用层 应用层是程序员打交道最多的一层,与应用程序直接相关 而应用层的协议,实际上就规定了你写的程序,通过网络传输的时候,按…

【LINUX】LINUX基础(目录结构、基本权限、基本命令)

文章目录 LINUX的目录结构LINUX的基本权限LINUX基本命令 LINUX的目录结构 /&#xff1a;表示根目录bin&#xff1a;存放二进制可执行文件(命令ls、cat、mkdir等)boot&#xff1a;存放系统引导文件dev&#xff1a;存放设备文件etc&#xff1a;存放系统配置文件home&#xff1a;…

LeeCode热题100(爬楼梯)

爬楼梯这个题我断断续续看了不下5遍&#xff0c;哪次看都是懵逼的&#xff0c;就会说是满足动态规划&#xff0c;满足斐波那契数列&#xff0c;也不说为什么。 本文一定让你明白怎么分析这个题的规律&#xff08;利用数学的递推思想来分析&#xff09;&#xff0c;看不懂来打我…

1114 全素日

你好哇&#xff0c;新的一天开始啦&#xff01; solution 取数值的不同部分&#xff0c;联想到借助string #include<iostream> #include<string> using namespace std; bool judge(string s){int n atoi(s.c_str());if(n 1 || n 0) return false;for(int i 2…

618大促买什么数码最划算?数码好物清单整理,买到就是赚到!

618年中大促数码产品爱好者们纷纷摩拳擦掌&#xff0c;准备在这个购物狂欢节里抢购心仪已久的数码好物&#xff0c;在繁多的品牌和型号中挑选出最划算的产品&#xff0c;并不是一件容易的事情&#xff0c;为了帮助大家更好地把握这次购物机会&#xff0c;我们精心整理了一份数码…