leetcode刷题小结 python备忘录


1. 处理输入

[list/tuple/dict(input().split()) for _ range(N)] # 对应有N行输入
map(int, input().split()) # 批量转换成int

2. 经典题目

计算器

3. 常用函数方法

3.1 列表推导式

new_list = [expression for item in iterable if condition]
- expression 是对每个元素执行的操作。
- item 是迭代中的当前项。
- iterable 是可迭代对象,如列表、元组、字符串等。
- if condition 是可选的过滤条件。

a.基本用法

squares = [x**2 for x in range(10)]
print(squares)  # 输出: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

b.带条件的列表推导式

even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares)  # 输出: [0, 4, 16, 36, 64]

c.嵌套列表推导式

matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

flattened_matrix = [num for row in matrix for num in row]
print(flattened_matrix)  # 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9]

d.复杂表达式

words = ['apple', 'banana', 'cherry']
word_lengths = [(word, len(word)) for word in words]
print(word_lengths)  # 输出: [('apple', 5), ('banana', 6), ('cherry', 6)]

3.2 .sort() / sorted() 的 key

a.字符串列表按长度排序

words = ['banana', 'pie', 'apple', 'cherry']
words.sort(key=len)
print(words)  # 输出: ['pie', 'apple', 'banana', 'cherry']

b.字典列表按照特定键排序

people = [
    {'name': 'Alice', 'age': 30},
    {'name': 'Bob', 'age': 25},
    {'name': 'Charlie', 'age': 35}
]

# 按年龄升序排列
people.sort(key=lambda person: person['age'])
print(people)
# 输出:
# [{'name': 'Bob', 'age': 25}, {'name': 'Alice', 'age': 30}, {'name': 'Charlie', 'age': 35}]

c.使用itemgetter进行排序
当需要根据多个字段进行排序时,可以使用operator.itemgetter,它比lambda函数更高效。

from operator import itemgetter

people = [
    {'name': 'Alice', 'age': 30, 'height': 165},
    {'name': 'Bob', 'age': 25, 'height': 175},
    {'name': 'Charlie', 'age': 30, 'height': 180}
]

# 先按年龄,再按身高排序
people.sort(key=itemgetter('age', 'height'))
print(people)
# 输出:
# [{'name': 'Bob', 'age': 25, 'height': 175}, {'name': 'Alice', 'age': 30, 'height': 165}, {'name': 'Charlie', 'age': 30, 'height': 180}]

3.3 .is[ anything ] ()函数

  • .isdigit():检查是否只包含数字
  • .isalpha():检查是否只包含字母
  • .isupper():检查是否只包含大写字母
  • .islower():检查是否只包含小写字母
  • .isalnum():检查是否只包含字母或数字
  • .lower():将字符串中的所有大写字母转换为小写字母。
  • .upper():将字符串中的所有小写字母转换为大写字母

3.4 chr() / ord()

3.5 divmod()

4 常用算法

4.1 二分查找

def binary_search(nums, target):
    left = 0
    right = len(nums) - 1  # 初始化右边界为数组最后一个索引
    
    while left <= right:  # 循环条件:当 left 小于等于 right 时继续循环
        mid = (left + right) // 2  # 计算中间位置
        
        if nums[mid] == target:
            return mid  # 找到目标值,返回其索引
        elif nums[mid] < target:
            left = mid + 1  # 目标值在右半部分
        else:
            right = mid - 1  # 目标值在左半部分
    
    return -1  # 如果没有找到目标值,返回 -1

4.2 矩阵4个方向扩散

while stack:
    x, y = stack.pop()
    if -1 < x < m and -1 < y < n and not visited[x][y] and digit_sum(x) + digit_sum(y) <= k:
        visited[x][y] = True
        ans += 1
        stack.extend([(x-1, y), (x+1, y), (x, y-1), (x, y+1)])

4.3 visited数组表示有无访问

4.4 哈夫曼树

5 常用数据结构的实现

5.1 树

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val  # 节点存储的值
        self.left = left  # 左子节点
        self.right = right  # 右子节点

# 二叉树还可以通过数组的方式存储
tree = [0] * n # 将此二叉树存放入数组tree当中,有如下的关系:
tree[0] = root # 根节点存放在array[0]中
tree[i] = i
tree[2*i + 1] = i.left # 左孩子存放在tree[2*i+1]
tree[2*i + 2] = i.right # 右孩子存放在Array[2*i+2]
tree[i-1 //2] = i.father # 节点i的父节点将位于索引 (i - 1) / 2的位置(如果i不是根节点)。

5.2 链表

class ListNode:
    def __init__(self, value=0, next=None):
        self.value = value  # 节点存储的值
        self.next = next    # 指向下一个节点的指针

6 装饰器

装饰器(Decorator)是 Python 中一种强大的语法特性,它允许你在不修改原函数代码的前提下,动态地为函数或方法添加新的功能。其本质是一个接收函数作为参数并返回一个新函数的可调用对象(通常是函数或类)。

6.1 简单装饰器示例

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("装饰器:函数执行前的操作")
        result = func(*args, **kwargs)  # 调用原函数
        print("装饰器:函数执行后的操作")
        return result
    return wrapper

@my_decorator
def say_hello(name):
    print(f"Hello, {name}!")

# 调用被装饰的函数
say_hello("Alice")
# 输出:
# 装饰器:函数执行前的操作
# Hello, Alice!
# 装饰器:函数执行后的操作
  • func: 被装饰的原始函数。
  • wrapper: 装饰器内部定义的嵌套函数,它“包装”了对 func的调用。wrapper函数接收*args**kwargs,确保它可以接受任意数量和类型的参数,从而适配任何被装饰的函数。
  • 返回wrapper: 装饰器函数必须返回 wrapper(或其他可调用对象),这样当调用原函数名时,实际执行的是 wrapper

6.2 带参数的装饰器

有时需要向装饰器本身传递参数,这需要在原有装饰器结构外再嵌套一层函数。

def repeat(times):
    """一个带参数的装饰器:重复执行函数指定次数"""
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(times):
                result = func(*args, **kwargs)
            return result  # 返回最后一次执行的结果
        return wrapper
    return decorator

@repeat(3)
def greet(name):
    print(f"Hi, {name}!")

greet("Bob")
# 输出:
# Hi, Bob!
# Hi, Bob!
# Hi, Bob!
  • repeat(times): 最外层函数,接收装饰器的参数 times
  • decorator(func): 中间层函数,接收被装饰的函数func
  • wrapper(*args, **kwargs): 最内层函数,执行核心逻辑(重复调用 func)。

6.3 functools.wraps 保持元信息

直接使用 wrapper 会丢失原函数的元信息(如 __name__, __doc__)。使用functools.wraps可以解决此问题。

from functools import wraps

def timing_decorator(func):
    @wraps(func)  # 保留原函数的元数据
    def wrapper(*args, **kwargs):
        import time
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} 执行耗时: {end - start:.4f} 秒")
        return result
    return wrapper

@timing_decorator
def slow_function():
    """一个模拟耗时的函数"""
    time.sleep(1)
    return "Done"

print(slow_function.__name__)  # 输出: slow_function (而不是 wrapper)
print(slow_function.__doc__)   # 输出: 一个模拟耗时的函数
slow_function() # 输出执行耗时

6.4 常用装饰器示例

6.4.1 记忆化 (@cache)

如前所述,@functools.cache 可以缓存函数结果,避免重复计算。

import functools

@functools.cache
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(10)) # 第一次计算
print(fibonacci(10)) # 直接从缓存获取,极快

实际实现,用一个哈希表存储入参和对应的结果,以空间换时间

6.4.2 类装饰器

装饰器也可以是类。类需要实现 __call__ 方法使其可调用。

class CountCalls:
    def __init__(self, func):
        self.func = func
        self.count = 0

    def __call__(self, *args, **kwargs):
        self.count += 1
        print(f"{self.func.__name__} 已被调用 {self.count} 次")
        return self.func(*args, **kwargs)

@CountCalls
def say_hi():
    print("Hi!")

say_hi() # 输出: say_hi 已被调用 1 次
say_hi() # 输出: say_hi 已被调用 2 次
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值