实现一个类 LRUCache,支持以下操作:
cache = LRUCache(2)# 容量为2cache.put(1, 1)cache.put(2, 2)print(cache.get(1))# 返回 1cache.put(3, 3) # 移除键 2print(cache.get(2))# 返回 -1(未找到)
要求:
用 OrderedDict 或双向链表 + 字典 实现;
get 和 put 都必须是 O(1) 时间复杂度。
要求:实现 get / put 操作,时间复杂度 O(1)
示例:
cache=LRUCache(2)cache.put(1, 1)cache.put(2, 2)print(cache.get(1)) # 输出 1cache.put(3, 3) # 删除键 2print(cache.get(2)) # 输出 -1
ifkeyinself.cache:self.cache.move_to_end(key)self.cache[key] =valueiflen(self.cache) >self.capacity:self.cache.popitem(last=False)
from collections import OrderedDictclass LRUCache:def __init__(self, capacity: int):self.cache = OrderedDict()self.capacity = capacitydef get(self, key: int) -> int:if key not in self.cache:return -1 # 如果key不存在,返回-1else:# 将访问的key移动到字典的末尾,表示最近使用过self.cache.move_to_end(key)return self.cache[key]def put(self, key: int, value: int) -> None:if key in self.cache:# 如果key已存在,先删除旧的键值对,然后再添加新的,这样可以保持顺序正确del self.cache[key]self.cache[key] = valueself.cache.move_to_end(key) # 移动到末尾表示最近使用过else:if len(self.cache) >= self.capacity:# 如果缓存已满,则删除最久未使用的项(OrderedDict的第一个元素)self.cache.popitem(last=False)self.cache[key] = valueself.cache.move_to_end(key) # 移动到末尾表示最近使用过# 使用示例:cache = LRUCache(2)cache.put(1, 1)cache.put(2, 2)print(cache.get(1)) # 返回 1cache.put(3, 3) # 该操作会使关键字 2 作废print(cache.get(2)) # 返回 -1 (未找到)cache.put(4, 4) # 该操作会使关键字 1 作废print(cache.get(1)) # 返回 -1 (未找到)print(cache.get(3)) # 返回 3print(cache.get(4)) # 返回 4
在这个实现中:
__init__ 方法初始化缓存的容量。
get 方法检查键是否存在于缓存中,如果存在,则将其移到字典的末尾(表示最近使用),然后返回其值。如果不存在,则返回-1。
put 方法首先检查键是否已存在,如果存在则更新其值并将其移到末尾。如果不存在,则先检查缓存是否已满,如果已满,则删除最久未使用的项(即字典中的第一个项),然后添加新的键值对并将其移到末尾。
这样,我们就实现了LRU缓存机制。
关键点总结
O(1) 时间复杂度:通过哈希表实现快速查找,双向链表实现快速插入/删除;
访问顺序维护:每次 get 或 put(新键)都将对应节点移至链表头部;
淘汰策略:链表尾部始终为最久未使用节点,容量超限时删除它。
如需完整 LeetCode 题目练习,可访问:LeetCode 146. LRU 缓存
https://leetcode.cn/problems/lru-cache/description/
编写程序,使用 asyncio + aiohttp 并发请求以下 URL 列表:
urls = ["https://example.com/a", "https://example.com/b", "https://example.com/c"]要求:
输出每个请求的响应状态码;
限制同时并发数量不超过 3;
加入超时与异常捕获逻辑。
import asyncioimport aiohttpasync def fetch(session, url):async with session.get(url) as response:return await response.text()async def main():urls = ['https://www.example.com','https://www.google.com','https://www.python.org','https://www.github.com']async with aiohttp.ClientSession() as session:tasks = [fetch(session, url) for url in urls]responses = await asyncio.gather(*tasks)for i, response in enumerate(responses):print(f"Response from {urls[i]}:")print(response[:100]) # 打印前100个字符作为示例print("..." * 5) # 添加省略号以简化输出# 运行主函数if __name__ == '__main__':asyncio.run(main())
程序解释:
导入库:导入 asyncio 和 aiohttp。
定义 fetch 函数:这是一个异步函数,它使用 aiohttp 的 ClientSession 来发起 GET 请求,并返回响应的文本内容。
定义 main 函数:这是主函数,它定义了一个 URL 列表,并使用 aiohttp.ClientSession 来管理会话。它创建了一个任务列表,每个任务对应一个 URL 的请求,然后使用 asyncio.gather 来并发执行这些任务。
打印响应:对于每个响应,程序打印出该 URL 的响应内容的前100个字符,并添加省略号以简化输出。
运行主函数:使用 asyncio.run(main()) 来运行主函数。
这个程序展示了如何使用 asyncio 和 aiohttp 进行并发 HTTP 请求,非常适合于网络爬虫和数据抓取任务。你可以根据需要修改 URL 列表和响应处理逻辑