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

07-10 1815阅读

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

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

每日一题——Python实现蓝桥杯 单词分析(举一反三+思想解读+逐步优化)五千字好文个人主页:用哲学编程-CSDN博客
每日一题——Python实现蓝桥杯 单词分析(举一反三+思想解读+逐步优化)五千字好文专栏:每日一题——举一反三
Python编程学习
Python内置函数

Python-3.12.0文档解读

目录

 我的写法

代码分析

时间复杂度分析

空间复杂度分析

总结

我要更强

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

优化后的代码:

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

优化后的代码:

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

优化后的代码:

复杂度分析

方法一:使用 collections.Counter

方法二:使用 heapq

方法三:手动维护最大值

总结

哲学和编程思想

方法一:使用 collections.Counter

哲学和编程思想

方法二:使用 heapq

哲学和编程思想

方法三:手动维护最大值

哲学和编程思想

总结

举一反三


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

每日一题——Python实现蓝桥杯 单词分析(举一反三+思想解读+逐步优化)五千字好文每日一题——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 可以快速计算字符出现的次数,并且它的构造器是经过优化的,性能优于手动构造字典。

        优化后的代码:
        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 优化排序过程

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

        优化后的代码:
        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='')

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

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

        优化后的代码:
        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  
        

        复杂度分析

        方法一:使用 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. 复杂度分析:理解算法的时间复杂度和空间复杂度是很重要的,它可以帮助你预测代码的性能,以及是否有优化的可能性。

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


VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]