每日一题——Python实现蓝桥杯 单词分析(举一反三+思想解读+逐步优化)五千字好文

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

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

Python-3.12.0文档解读

目录

我的写法

代码分析

时间复杂度分析

空间复杂度分析

总结

我要更强

[方法一:使用 collections.Counter 优化字符计数](#方法一:使用 collections.Counter 优化字符计数)

优化后的代码:

[方法二:使用 heapq 优化排序过程](#方法二:使用 heapq 优化排序过程)

优化后的代码:

方法三:手动维护最大值优化

优化后的代码:

复杂度分析

[方法一:使用 collections.Counter](#方法一:使用 collections.Counter)

[方法二:使用 heapq](#方法二:使用 heapq)

方法三:手动维护最大值

总结

哲学和编程思想

[方法一:使用 collections.Counter](#方法一:使用 collections.Counter)

哲学和编程思想

[方法二:使用 heapq](#方法二:使用 heapq)

哲学和编程思想

方法三:手动维护最大值

哲学和编程思想

总结

举一反三


题目链接:https://www.lanqiao.cn/problems/504/learning/?page=1\&first_category_id=1\&difficulty=20\&sort=students_count\&asc=0

我的写法

python 复制代码
import os
import sys
word=input()
char_counts={}
for char in word:
    if char not in char_counts:
        char_counts[char]=1
    else:
        char_counts[char]+=1


print(*sorted(char_counts.items(),key=lambda x:(-x[1],x[0]))[0],sep='\n',end='')

代码分析

  1. 输入处理:
  2. 字符计数:
  3. 排序和输出:

这部分代码首先将字典 char_counts 的键值对转换为列表,然后使用 sorted 函数按指定的规则排序。排序规则是先按出现次数的负值(即从高到低)排序,如果出现次数相同则按字符的字典序排序。最后,输出排序后的第一个元素(即出现次数最多的字符及其出现次数)。

时间复杂度分析

  • 字符计数部分:遍历输入字符串的时间复杂度是 O(n),其中 n 是输入字符串的长度。
  • 排序部分:排序的时间复杂度是 O(m log m),其中 m 是不同字符的数量。在最坏情况下,m 可能等于 n,但通常 m 远小于 n。

综合来看,整个代码的时间复杂度主要由排序部分决定,因此总体时间复杂度为 O(n + m log m)。

空间复杂度分析

  • 字符计数部分:使用了一个字典 char_counts 来存储字符及其出现次数,因此空间复杂度是 O(m),其中 m 是不同字符的数量。
  • 排序部分:排序过程中需要一个临时列表来存储字典的键值对,因此空间复杂度也是 O(m)。

综合来看,整个代码的空间复杂度为 O(m)。

总结

  • 时间复杂度:O(n + m log m)
  • 空间复杂度:O(m)

这段代码在处理大量数据时可能会受到排序操作的影响,但总体来说,它在时间和空间效率上都是合理的。


我要更强

当然,可以对这段代码进行优化。以下是几种可能的优化方式:

方法一:使用 collections.Counter 优化字符计数

collections.Counter 可以快速计算字符出现的次数,并且它的构造器是经过优化的,性能优于手动构造字典。

优化后的代码:
python 复制代码
import collections

word = input()
char_counts = collections.Counter(word)

# 按照出现次数从高到低排序,出现次数相同时按字符字典序排序
most_common_char = sorted(char_counts.items(), key=lambda x: (-x[1], x[0]))[0]

# 输出结果
print(*most_common_char, sep='\n', end='')

方法二:使用 heapq 优化排序过程

对于寻找出现次数最多的字符,可以使用堆数据结构,这样可以优化排序操作。

优化后的代码:
python 复制代码
import collections
import heapq

word = input()
char_counts = collections.Counter(word)

# 使用堆来获取出现次数最多的字符
most_common_char = heapq.nlargest(1, char_counts.items(), key=lambda x: (x[1], -ord(x[0])))[0]

# 输出结果
print(*most_common_char, sep='\n', end='')

方法三:手动维护最大值优化

在遍历字符串的过程中,手动维护一个最大值,这样可以避免对整个字典进行排序。

优化后的代码:
python 复制代码
word = input()
char_counts = {}
max_char = ''
max_count = 0

for char in word:
    if char not in char_counts:
        char_counts[char] = 1
    else:
        char_counts[char] += 1
    
    # 更新最大值
    if (char_counts[char] > max_count) or (char_counts[char] == max_count and char < max_char):
        max_count = char_counts[char]
        max_char = char

# 输出结果
print(max_char, max_count, sep='\n', end='')

复杂度分析

方法一:使用 collections.Counter
  • 时间复杂度:
    • 建立 Counter 的时间复杂度是 O(n)。
    • 排序的时间复杂度是 O(m log m)。
  • 空间复杂度:O(m)
方法二:使用 heapq
  • 时间复杂度:
    • 建立 Counter 的时间复杂度是 O(n)。
    • 使用堆获取最大值的时间复杂度是 O(m log k),这里 k = 1,因此简化为 O(m)。
  • 空间复杂度:O(m)
方法三:手动维护最大值
  • 时间复杂度:整个过程只需要一次遍历字符串,时间复杂度是 O(n)。
  • 空间复杂度:O(m)

总结

  • 方法一和方法二在构建字符计数时都使用了 Counter,在处理大数据时,性能优于手动字典构建。
  • 方法二通过堆优化了排序过程,适用于需要获取前 k 个最大值的情况。
  • 方法三直接在遍历过程中维护最大值,在时间和空间复杂度上都是最优的。

可以根据具体需求选择适合的优化方案。


哲学和编程思想

在代码优化过程中,可以应用一些哲学和编程思想来设计更高效、更可读的解决方案。以下是对上述方法中使用的哲学和编程思想的详细说明:

方法一:使用 collections.Counter

哲学和编程思想
  1. 开源工具复用:
    • 哲学:不要重复发明轮子(DRY - Don't Repeat Yourself)。
    • 编程思想:利用现有的高效库和工具可以节省时间和精力,同时提高代码的性能和可靠性。collections.Counter 是一个专门用于计数的高效工具。
  2. 抽象化:
  • 哲学:将复杂的问题抽象为更简单的子问题。
  • 编程思想:通过使用高层次的抽象,如 Counter,我们可以避免手动管理计数逻辑,从而简化代码。

方法二:使用 heapq

哲学和编程思想
  1. 数据结构选择:
    • 哲学:选择最合适的数据结构解决问题。
    • 编程思想:堆是一种适合处理优先级队列的高效数据结构,能够在 O(log n) 时间内完成插入和删除操作。heapq 用于高效地找到前 k 个最大/最小元素。
  2. 分而治之:
  • 哲学:将问题分解为更小的子问题,逐一解决。
  • 编程思想:通过使用堆来处理排序问题,可以将问题分解为插入和删除操作,避免全局排序。

方法三:手动维护最大值

哲学和编程思想
  1. 原地计算(In-place Calculation):
    • 哲学:尽量减少空间占用,直接在现有数据上进行计算。
    • 编程思想:通过在遍历过程中直接维护最大值,避免了额外的空间开销和排序操作。
  2. 贪心算法:
  • 哲学:在每一步选择中做出局部最优解,从而达到全局最优解。
  • 编程思想:在每次字符计数更新时,立即检查并更新最大值,确保总是能够得到当前的全局最优解。

总结

这些优化方法利用了多种哲学和编程思想,如开源工具复用、抽象化、数据结构选择、分而治之、原地计算和贪心算法。这些思想不仅帮助我们编写高效的代码,还提高了代码的可读性和可维护性。通过理解和应用这些思想,我们可以设计出更加优雅和高效的解决方案。


举一反三

根据上述的哲学和编程思想,以下是一些具体的技巧,可以帮助将这些原则应用到其他问题中:

  1. 理解并利用现有的库和工具:在 Python 中,有很多预建的库和工具可供使用,如 collections、heapq 等。了解这些工具可以提供的功能,可以帮助你更高效地解决问题,而不必从头开始编写代码。
  2. 选择合适的数据结构:解决问题时,选择合适的数据结构是至关重要的。例如,如果你需要频繁地查找、添加或删除元素,那么可能应该选择如集合(set)或字典(dictionary)。如果需要排列或排序数据,考虑使用列表(list)或堆(heap)。
  3. 使用抽象化简化问题:试图将复杂问题抽象化,或者分解成更小的、更易于处理的部分。例如,你可以创建辅助函数来处理某些重复的任务,或者使用类(class)和对象(object)来模拟现实世界的情况。
  4. 贪心算法:在处理优化问题时,贪心算法是一种有效的策略。每次做出当前看起来最好的选择,最终可能得到全局最优解。但要注意,贪心算法并不总是能得到最优解,需要根据具体问题来分析。
  5. 原地计算:如果可能,尽量在原地进行计算,以减少额外的空间需求。例如,使用列表的索引进行操作,而不是创建新的列表。
  6. 预处理优化:在开始主要计算之前,通过预处理输入数据来简化问题或提高效率。例如,使用 Counter 进行预计数,或者对数据进行排序或分类。
  7. 复杂度分析:理解算法的时间复杂度和空间复杂度是很重要的,它可以帮助你预测代码的性能,以及是否有优化的可能性。

记住,这些只是工具和方法,应用哪种取决于具体的问题和场景。在实际编程中,需要灵活运用,甚至需要综合利用多种技巧和思想来解决问题。


相关推荐
麦田里的稻草人w4 分钟前
【YOLO】(基础篇一)YOLO介绍
人工智能·python·神经网络·yolo·机器学习
Bruce_Liuxiaowei6 分钟前
Python编程构建动态的圣诞画面
开发语言·python
凭君语未可6 分钟前
详解归并排序
算法·排序算法
simple_ssn12 分钟前
【蓝桥杯】走迷宫
java·算法
simple_ssn12 分钟前
【蓝桥杯】奇怪的捐赠
java·算法
wang_yb13 分钟前
Python包管理不再头疼:uv工具快速上手
python·databook
山川而川-R37 分钟前
ubuntu22.04安装PaddleX3
python·ocr
从以前1 小时前
【算法题解】Bindian 山丘信号问题(E. Bindian Signaling)
开发语言·python·算法
不白兰1 小时前
[代码随想录23回溯]回溯的组合问题+分割子串
算法