一个认为一切根源都是“自己不够强”的INTJ
个人主页:用哲学编程-CSDN博客
专栏:每日一题——举一反三
题目链接
我的写法:
nums_sounds={0:'ling',1:'yi',2:'er',3:'san',4:'si',5:'wu',6:'liu',7:'qi',8:'ba',9:'jiu',
}sum=0inputs=input()
input_nums=[]
for i in inputs:sum+=eval(i)sum=str(sum)index=1
for i in sum:print(nums_sounds[eval(i)],end='')if index<len(sum):print(end=' ')index+=1
代码点评:
这段代码的主要功能是读取用户输入的一串数字,计算这些数字的总和,然后将总和的每一位数字转换为对应的中文读音,并按顺序输出。下面是对这段代码的专业点评:
代码结构和功能
- 字典定义:定义了一个字典nums_sounds,将数字0-9映射到它们的中文读音。
- 初始化:初始化一个变量sum为0,用于存储数字的总和。
- 用户输入:通过input()函数获取用户输入,并将其存储在inputs变量中。
- 求和:遍历用户输入的每个字符,将其转换为数字并累加到sum中。
- 转换为字符串:将sum转换为字符串,以便逐个处理每一位数字。
- 输出中文读音:遍历sum字符串的每一位,将其转换为数字,然后查找对应的读音并输出。如果当前位不是最后一位,则在读音后添加一个空格。
时间复杂度分析
- 用户输入:input()函数的时间复杂度可以忽略不计,因为它通常是常数时间。
- 求和:遍历用户输入的每个字符,时间复杂度为O(n),其中n是用户输入的字符数。
- 转换为字符串:将整数转换为字符串的时间复杂度为O(log sum),因为整数的位数是其对数。
- 输出中文读音:遍历sum字符串的每一位,时间复杂度为O(log sum)。
总的时间复杂度为O(n + log sum),其中n是用户输入的字符数,sum是用户输入数字的总和。在最坏的情况下,如果用户输入的数字非常多,时间复杂度将接近O(n)。
空间复杂度分析
- 字典nums_sounds:存储了10个键值对,空间复杂度为O(1)。
- 用户输入:存储用户输入的字符串,空间复杂度为O(n),其中n是用户输入的字符数。
- 变量sum:存储数字的总和,空间复杂度为O(1)。
- 变量inputs和input_nums:虽然代码中声明了这两个变量,但实际上input_nums没有被使用,因此它们的空间复杂度可以忽略。
总的空间复杂度为O(n),主要由用户输入的字符串决定。
改进建议
- 变量使用:变量input_nums没有被使用,可以删除以避免混淆。
- 安全性:使用eval()函数处理用户输入是不安全的,因为它会执行任意代码。应该使用int()函数将字符转换为整数。
- 代码清晰度:可以在输出中文读音时,直接使用字典nums_sounds的键来查找值,而不是使用eval()函数。
- 错误处理:代码没有处理用户输入非数字字符的情况,可以添加错误处理逻辑。
综上所述,这段代码实现了预期的功能,但在安全性和代码清晰度方面有改进空间。时间复杂度在最坏情况下接近O(n),空间复杂度为O(n)。
我要更强!
对于这段代码,由于它的主要操作是基于输入字符串的逐字符处理,时间复杂度的优化空间相对有限。不过,我们可以通过几种方式来改进代码的效率和安全性,同时尽可能降低空间使用。
优化时间复杂度
- 直接求和:由于我们最终关心的是输入数字的和,可以在处理输入字符串时直接累加数值,而不是首先转换成数字再求和。这里没有明显的时间复杂度降低,因为主要瓶颈在于对输入字符串的遍历,但这样可以减少不必要的转换步骤,提高代码效率。
优化代码(非时间复杂度)
- 使用int()而非eval():为了安全性,应当使用int(i)替换eval(i)进行字符串到整数的转换。
- 减少不必要的变量:由于input_nums未使用,可以将其删除,以简化代码。
优化空间复杂度
- 减少临时存储:由于最终只需要输出数字的和的中文读音,不需要存储中间转换的任何数组或列表,所以实际上空间复杂度已经是比较优化的了。确保不创建不必要的数据结构,可以保持空间复杂度最小。
优化后的代码
nums_sounds = {0: 'ling',1: 'yi',2: 'er',3: 'san',4: 'si',5: 'wu',6: 'liu',7: 'qi',8: 'ba',9: 'jiu',
}# 初始化总和为0
sum = 0# 获取输入并直接计算总和
inputs = input()
for i in inputs:sum += int(i) # 安全地将每个字符转换为整数并累加# 将总和转换为字符串,以便逐个处理每个数字
sum_str = str(sum)# 输出对应的中文读音
for index, i in enumerate(sum_str):print(nums_sounds[int(i)], end='')if index < len(sum_str) - 1:print(' ', end='')
结论
虽然针对这个特定问题的时间复杂度优化空间有限(主要受限于输入字符串的长度),通过上述修改,代码变得更加安全、简洁。最重要的是,我们已经采取措施降低了空间复杂度到最低,即O(1)的额外空间(不计算输入字符串和最终输出所占的空间)。
这种方法用到哪些哲学和编程思想
这段代码的实现和优化体现了以下哲学和编程思想:
1. 简单性(Simplicity)
- KISS原则(Keep It Simple, Stupid):代码应该尽可能简单,避免不必要的复杂性。优化后的代码删除了未使用的变量,简化了求和过程,使得代码更加清晰易懂。
2. 安全性(Security)
- 最小权限原则(Principle of Least Privilege):在编程中,应该只使用完成任务所必需的最小权限。通过避免使用eval()函数,代码减少了执行潜在恶意代码的风险。
3. 效率(Efficiency)
- 优化算法和数据结构:虽然在这个特定情况下时间复杂度的优化空间有限,但通过直接累加数值而不是先转换再求和,代码提高了执行效率。
4. 可读性(Readability)
- 代码即文档(Code as Documentation):良好的代码应该是自解释的,变量名和函数名应该清晰地反映其用途。在这个例子中,nums_sounds字典的命名清晰地表明了其用途。
5. 迭代和改进(Iteration and Improvement)
- 迭代开发(Iterative Development):代码的优化过程体现了迭代开发的思想,即通过不断的小步骤改进来完善代码。
6. 抽象(Abstraction)
- 使用字典进行映射:通过使用字典nums_sounds,代码抽象了数字到中文读音的映射关系,使得代码更加模块化和可维护。
7. 错误预防(Error Prevention)
- 防御性编程(Defensive Programming):虽然代码没有显式地处理错误,但通过避免使用eval()函数,代码预防了潜在的安全错误。
8. 单一职责原则(Single Responsibility Principle)
- 模块化设计:每个函数或代码块应该只有一个职责。在这个例子中,每个部分(输入处理、求和、输出)都专注于完成一个特定的任务。
9. 可扩展性(Scalability)
- 设计可扩展的代码:虽然在这个简单的例子中不明显,但通过保持代码的模块化和简单性,可以更容易地在未来添加新功能或处理更复杂的情况。
举一反三:
通过从前述优化方法中提取的哲学和编程原则,可以应用以下技巧来提高编程技能,使你能够在不同的场景下举一反三:
1. 追求简洁明了的代码
- 削减不必要的代码:定期审查代码,移除未使用的变量和函数。这不仅能提高代码的清晰度,还可以减少潜在的错误来源。
- 简化逻辑:尽可能简化算法和逻辑。如果有两种方式实现相同的功能,选择更简单的那一种。
2. 注重代码的安全性
- 避免使用危险函数:识别并避免使用那些可能导致安全漏洞的函数,如eval()。
- 输入验证:总是验证外部输入,防止注入攻击或不良数据破坏应用程序。
3. 提高效率
- 算法优化:学习和应用数据结构和算法的知识,以找到更有效率的解决方案。
- 利用空间换时间:在可接受的空间复杂度范围内,考虑使用数据缓存等技术来提高程序执行的速度。
4. 重视可读性和维护性
- 命名规范:使用有意义且一致的命名规范,使得其他开发者(或未来的你)可以更容易理解代码的意图。
- 分解大型任务:将复杂的任务分解成小的、可管理的函数或模块,每个都只负责一个具体的功能。
5. 定期重构
- 重构以提升质量:不要害怕重构代码以提高其可读性、安全性或性能。随着需求的演变和技术的进步,代码重构是必要的。
6. 编写可扩展的代码
- 设计模式:学习和应用设计模式,以编写高效、可重用且易于扩展的代码。
- 模块化:保持代码的高内聚低耦合,使各部分之间的依赖最小化,从而简化未来的修改和扩展。
7. 持续学习和实践
- 学习新技术:定期学习新的编程语言、工具和最佳实践,保持你的技能与时俱进。
- 代码评审:参与代码评审,学习他人的优秀实践,并接受建设性的反馈来改进自己的代码。
以上为本期全部内容,感谢阅读。