每日一题——只需一行Python秒杀:PAT乙级1009 说反话!但不能故步自封!(举一反三+思想解读+逐步优化)


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

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

Python-3.12.0文档解读

目录

我的写法

各部分功能分析:

综合时间复杂度

综合空间复杂度

总结

思路扩充

方法1: 使用双端队列

方法2: 使用栈

方法3: 使用递归

方法4: 原地反转

总结

哲学和编程思想

1. 简洁性 (Simplicity)

2. 高内聚 (High Cohesion)

3. 面向表达式编程 (Expression-Oriented Programming)

4. 函数式编程 (Functional Programming)

5. 内置函数和标准库的使用 (Leveraging Built-In Functions and Standard Library)

6. 声明式编程 (Declarative Programming)

7. 最少惊讶原则 (Principle of Least Astonishment)

8. 单一职责原则 (Single Responsibility Principle)

9. 组合模式 (Composition over Inheritance)

总结

举一反三

技巧1:简洁性 (Simplicity)

技巧2:高内聚 (High Cohesion)

技巧3:面向表达式编程 (Expression-Oriented Programming)

技巧4:函数式编程 (Functional Programming)

技巧5:声明式编程 (Declarative Programming)

技巧6:最少惊讶原则 (Principle of Least Astonishment)

技巧7:单一职责原则 (Single Responsibility Principle)

技巧8:组合模式 (Composition over Inheritance)

总结


题目链接


我的写法

print(*input().split()[::-1])


 

这段代码的功能是倒序输出用户输入的一行文本中的单词。

各部分功能分析:

  1. input():
    • 等待用户输入一行文本,并返回输入的字符串。
    • 时间复杂度:O(n),其中 n 是输入字符串的长度。
    • 空间复杂度:O(n),用于存储输入的字符串。
  2. split():
    • 将输入的字符串按照空白字符(如空格)进行分割,返回一个包含各个单词的列表。
    • 时间复杂度:O(n),需要扫描整个输入字符串。
    • 空间复杂度:O(k),其中 k 是分割后的单词列表的长度。每个单词也是从输入字符串中分割出来的,没有额外的空间分配。
  3. [::-1]:
    • 对分割后的单词列表进行逆序操作。
    • 时间复杂度:O(k),需要遍历整个列表。
    • 空间复杂度:O(k),会创建一个新的列表来存储逆序后的元素。
  4. print(*...):
  • 使用 * 运算符将列表的元素解包为单独的参数传递给 print() 函数,从而实现倒序输出每个单词。
  • 时间复杂度:O(k),需要遍历每个单词。
  • 空间复杂度:O(1),print() 本身不需要额外的空间来存储数据,但每个单词会分别传递给 print()。

综合时间复杂度

  • 输入操作:O(n)
  • 分割操作:O(n)
  • 逆序操作:O(k)
  • 打印操作:O(k)

由于 n 是输入字符串的长度,而 k 是分割后的单词数,且 k <= n,可以认为综合时间复杂度为 O(n)。

综合空间复杂度

  • 输入字符串:O(n)
  • 分割后的单词列表:O(k)
  • 逆序后的列表:O(k)

综合空间复杂度为 O(n),因为存储输入字符串是主要的空间消耗。

总结

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

这段代码非常简洁且高效地实现了倒序输出输入行中的单词。由于 Python 内置函数的高效实现,整体性能表现良好,适用于处理一般长度的输入文本。


思路扩充

有其他方法可以实现同样的功能。下面是另外几种方法,包括一些使用不同编程范式和数据结构的实现方法。虽然这些方法的时间复杂度和空间复杂度未必能显著超越原来的实现,但它们提供了不同的视角和编程技巧。

方法1: 使用双端队列

双端队列(deque)允许我们高效地在两端插入和删除元素。我们可以利用这一特性来实现反转单词的功能。

from collections import deque

def reverse_words_deque():
    import sys
    input_line = sys.stdin.readline().strip()
    
    # 使用双端队列
    dq = deque()
    current_word = []
    
    for char in input_line:
        if char.isspace():
            if current_word:
                dq.appendleft(''.join(current_word))
                current_word = []
        else:
            current_word.append(char)
    
    if current_word:
        dq.appendleft(''.join(current_word))
    
    print(' '.join(dq))

if __name__ == "__main__":
    reverse_words_deque()

方法2: 使用栈

栈的后进先出(LIFO)特性使得它非常适合这个任务。我们可以将单词依次推入栈中,然后依次弹出即可实现反转。

def reverse_words_stack():
    import sys
    input_line = sys.stdin.readline().strip()
    
    stack = []
    current_word = []
    
    for char in input_line:
        if char.isspace():
            if current_word:
                stack.append(''.join(current_word))
                current_word = []
        else:
            current_word.append(char)
    
    if current_word:
        stack.append(''.join(current_word))
    
    while stack:
        print(stack.pop(), end=' ')
    
    print()

if __name__ == "__main__":
    reverse_words_stack()

方法3: 使用递归

递归方法虽然不一定是最优的,但它提供了一种有趣的变换方式。

def reverse_words_recursive(words):
    if not words:
        return
    word = words.pop()
    print(word, end=' ')
    reverse_words_recursive(words)

def main_recursive():
    import sys
    input_line = sys.stdin.readline().strip()
    words = input_line.split()
    reverse_words_recursive(words)
    print()

if __name__ == "__main__":
    main_recursive()

方法4: 原地反转

如果允许修改输入字符串,可以考虑原地反转。虽然Python字符串不可变,但我们可以用列表模拟这一操作。

def reverse_words_in_place():
    import sys
    input_line = list(sys.stdin.readline().strip())
    
    def reverse_range(lst, start, end):
        while start < end:
            lst[start], lst[end] = lst[end], lst[start]
            start += 1
            end -= 1
    
    n = len(input_line)
    reverse_range(input_line, 0, n - 1)
    
    start = 0
    for i in range(n + 1):
        if i == n or input_line[i].isspace():
            reverse_range(input_line, start, i - 1)
            start = i + 1
    
    print(''.join(input_line))

if __name__ == "__main__":
    reverse_words_in_place()

总结

以上几种方法展示了如何从不同的角度实现“反转单词”的功能:

  1. 双端队列:高效的插入和删除操作。
  2. 栈:利用后进先出的特性。
  3. 递归:虽然不一定高效,但提供了另一种实现思路。
  4. 原地反转:模拟C语言风格的原地操作。

每种方法都有其独特的应用场景和优缺点。从实际应用角度看,原始代码已经足够高效,但了解不同的实现方法能帮助你在不同场景中灵活应用。


哲学和编程思想

使用这段代码解决问题不仅简洁高效,还体现了多种重要的编程哲学和思想。以下是一些关键点:

1. 简洁性 (Simplicity)

这段代码采用了Python的内置函数和操作符,直接实现了功能,非常简洁。简洁性是编程中的一大美德,代码越简洁,越容易阅读、理解和维护。

2. 高内聚 (High Cohesion)

这段代码中的每个部分都有明确的职责:input()用于读取输入,split()用于分割单词,[::-1]用于反转列表,print(*...)用于输出结果。这种高内聚性使得代码更容易理解和调试。

3. 面向表达式编程 (Expression-Oriented Programming)

Python是一种表达式导向的语言,这段代码充分利用了Python的表达式能力。通过链式调用,多个操作被组合成一个表达式,这使得代码更紧凑。

4. 函数式编程 (Functional Programming)

虽然Python不是纯粹的函数式编程语言,但这段代码展示了一些函数式编程的概念,比如:

  • 无副作用 (Side-Effect Free):代码读取输入,处理数据,然后输出结果,没有修改任何全局状态。
  • 不可变性 (Immutability):split()和[::-1]操作返回新的列表,而不是修改原列表。

5. 内置函数和标准库的使用 (Leveraging Built-In Functions and Standard Library)

Python的内置函数和标准库提供了高效且经过优化的实现。通过利用这些函数(如input(), split(), print()),我们可以减少代码量并提高执行效率。

6. 声明式编程 (Declarative Programming)

这段代码更多的是描述了“做什么”,而不是“如何做”。例如,split()描述了要把字符串拆分成单词,[::-1]描述了要反转列表,而不是手动实现这些操作。这种声明式的风格提高了代码的可读性和可维护性。

7. 最少惊讶原则 (Principle of Least Astonishment)

代码的行为符合大多数程序员的预期,没有复杂的操作和隐藏的副作用。这使得代码更容易理解和信任。

8. 单一职责原则 (Single Responsibility Principle)

这段代码的每个部分都只有一个明确的职责:读取输入、分割单词、反转列表和打印输出。这符合单一职责原则,使得代码更模块化。

9. 组合模式 (Composition over Inheritance)

虽然这段代码没有涉及到类和继承,但它展示了通过组合简单操作来构建复杂功能的方法。这种组合模式是很多现代编程的核心思想,比继承更灵活、更易于维护。

总结

这段代码通过简洁、高内聚、函数式编程和内置函数的高效使用,展示了许多编程中的重要思想和哲学。这不仅使代码易于阅读和维护,也提高了代码的执行效率。通过这些编程思想的应用,可以编写出更高质量、更可靠的代码。


举一反三

当然,理解这些编程哲学和思想并能在实际编程中灵活应用是非常有价值的。以下是一些具体的技巧和示例代码,帮助你在编写代码时能够举一反三。

技巧1:简洁性 (Simplicity)

技巧:利用Python的内置函数和简洁语法,使代码尽可能简洁。

示例:将一个字符串中的所有数字提取出来,并以列表形式返回。

# 简洁方式
def extract_digits(s):
    return [int(char) for char in s if char.isdigit()]

# 使用示例
s = "ab12cd34"
print(extract_digits(s))  # 输出: [1, 2, 3, 4]

技巧2:高内聚 (High Cohesion)

技巧:确保每个函数或代码块只做一件事,这有助于代码的可读性和可维护性。

示例:将输入的句子转换成大写,并按单词反转。

def read_input():
    return input("Enter a sentence: ")

def to_uppercase(s):
    return s.upper()

def reverse_words(s):
    return ' '.join(s.split()[::-1])

def main():
    sentence = read_input()
    uppercase_sentence = to_uppercase(sentence)
    reversed_sentence = reverse_words(uppercase_sentence)
    print(reversed_sentence)

# 使用示例
if __name__ == "__main__":
    main()

技巧3:面向表达式编程 (Expression-Oriented Programming)

技巧:尽可能使用表达式来进行链式操作,使代码更紧凑。

示例:从一个列表中筛选出所有偶数,并将它们平方后返回。

# 面向表达式编程
def filter_and_square_evens(nums):
    return [x**2 for x in nums if x % 2 == 0]

# 使用示例
nums = [1, 2, 3, 4, 5, 6]
print(filter_and_square_evens(nums))  # 输出: [4, 16, 36]

技巧4:函数式编程 (Functional Programming)

技巧:尽量避免副作用,使用不可变的数据结构和纯函数。

示例:对列表中的每个元素应用一个函数,并返回新的列表。

# 函数式编程
def apply_function(lst, func):
    return list(map(func, lst))

# 使用示例
nums = [1, 2, 3, 4]
print(apply_function(nums, lambda x: x * 2))  # 输出: [2, 4, 6, 8]

技巧5:声明式编程 (Declarative Programming)

技巧:更多地描述“做什么”,而不是“如何做”。

示例:从一个字符串中提取所有的单词,并按字母顺序排序。

# 声明式编程
def extract_and_sort_words(s):
    return sorted(s.split())

# 使用示例
s = "the quick brown fox"
print(extract_and_sort_words(s))  # 输出: ['brown', 'fox', 'quick', 'the']

技巧6:最少惊讶原则 (Principle of Least Astonishment)

技巧:编写代码时,尽量避免复杂和不易理解的逻辑,遵循常见的编程习惯。

示例:创建一个简单的计算器函数,可以进行加、减、乘、除操作。

# 最少惊讶原则
def calculator(a, b, operation):
    if operation == 'add':
        return a + b
    elif operation == 'subtract':
        return a - b
    elif operation == 'multiply':
        return a * b
    elif operation == 'divide':
        if b != 0:
            return a / b
        else:
            return 'Division by zero'
    else:
        return 'Unknown operation'

# 使用示例
print(calculator(10, 5, 'add'))  # 输出: 15
print(calculator(10, 5, 'divide'))  # 输出: 2.0

技巧7:单一职责原则 (Single Responsibility Principle)

技巧:每个函数或类只负责一项任务。

示例:设计一个简单的用户管理系统,每个类和函数都有明确的职责。

class User:
    def __init__(self, username, email):
        self.username = username
        self.email = email

class UserManager:
    def __init__(self):
        self.users = []

    def add_user(self, user):
        self.users.append(user)

    def remove_user(self, username):
        self.users = [user for user in self.users if user.username != username]

    def get_user(self, username):
        for user in self.users:
            if user.username == username:
                return user
        return None

# 使用示例
user1 = User('alice', 'alice@example.com')
user2 = User('bob', 'bob@example.com')

manager = UserManager()
manager.add_user(user1)
manager.add_user(user2)

print(manager.get_user('alice').email)  # 输出: alice@example.com
manager.remove_user('alice')
print(manager.get_user('alice'))  # 输出: None

技巧8:组合模式 (Composition over Inheritance)

技巧:通过组合简单功能来构建复杂功能,而不是通过继承来扩展功能。

示例:实现一个具有加法和乘法功能的计算器,并使用组合方式扩展新的功能。

class Adder:
    def add(self, a, b):
        return a + b

class Multiplier:
    def multiply(self, a, b):
        return a * b

class Calculator:
    def __init__(self, adder, multiplier):
        self.adder = adder
        self.multiplier = multiplier

    def add(self, a, b):
        return self.adder.add(a, b)

    def multiply(self, a, b):
        return self.multiplier.multiply(a, b)

# 使用示例
adder = Adder()
multiplier = Multiplier()
calculator = Calculator(adder, multiplier)

print(calculator.add(3, 4))  # 输出: 7
print(calculator.multiply(3, 4))  # 输出: 12

总结

通过这些技巧和示例代码,可以更好地理解和应用编程中的重要思想和哲学。这不仅有助于写出更高效、更易维护的代码,还能提高编程技能和思维能力。


感谢阅读。

  • 10
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

用哲学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值