kimi-k2.6 在「实现LRU缓存」的评测结果
这是该 AI 模型在此测试用例上的详细评测结果。
基本信息
- 模型名称:kimi-k2.6
- 用例名称:实现LRU缓存
- 测试类型:文本生成
- 评测维度:代码生成
系统提示词(System Prompt)
这是给 AI 模型的背景设定和角色指令:
你是一名资深软件工程师,专注于数据结构与算法设计,熟悉 Python 语言规范。 回答要求: 1. 使用 Python 实现,代码需符合 PEP 8 规范,变量与方法命名清晰易读。 2. 必须使用「双向链表 + 哈希表」组合实现,并在代码注释或说明中解释选择该数据结构的原因。 3. 实现完成后,给出至少 3 个测试用例(含预期输出),覆盖正常操作与缓存淘汰场景。 4. 对核心逻辑(节点移动、淘汰操作)添加简短注释,帮助读者理解指针操作。
用户提示词(User Prompt)
这是用户给 AI 模型的具体任务要求:
请使用 Python 实现一个 LRU(最近最少使用)缓存类 `LRUCache`,具体要求如下: **功能要求:** - `__init__(self, capacity: int)`:初始化缓存,`capacity` 为正整数,表示缓存最大容量。 - `get(self, key: int) -> int`: - 若 `key` 存在于缓存中,返回对应的值,并将该项标记为「最近使用」。 - 若 `key` 不存在,返回 `-1`。 - `put(self, key: int, value: int) -> None`: - 若 `key` 已存在,更新其值,并将该项标记为「最近使用」。 - 若 `key` 不存在,插入新项。若插入后超出容量,则删除「最久未使用」的项。 **实现约束:** - `get` 和 `put` 操作的时间复杂度均须为 **O(1)**。 - 必须使用「双向链表 + 哈希表」实现,不得直接使用 `collections.OrderedDict` 等封装好 LRU 语义的标准库。 - 推荐使用哑节点(dummy head / tail)简化链表边界处理。 **示例:**
评测结果
综合得分
该模型在此用例的得分为:95.2 分(满分 100 分),已通过
基础难度评测结果
- 得分:95.2 分
- 通过状态:已通过
模型生成产物
以下是该模型针对此任务的实际生成内容:
```python class _ListNode: """双向链表节点,同时存储 key 与 value。 存储 key 的目的是:当从尾部淘汰节点时,能根据 node.key 在哈希表中定位并删除对应的映射,而无需再次遍历。 """ def __init__(self, key: int = 0, value: int = 0): self.key = key self.value = value self.prev = None self.next = None class LRUCache: """LRU(最近最少使用)缓存。 数据结构说明: 1. 哈希表(dict):key -> _ListNode,提供 O(1) 的查找能力。 2. 双向链表:按使用顺序维护节点,越靠近头部表示越「最近使用」, 越靠近尾部表示越「久未使用」。 双向结构保证在已知节点引用时,删除和移动操作均为 O(1)。 3. 哑节点(dummy head / tail):避免对空链表或头尾节点的 特殊判空处理,统一指针操作逻辑。 """ def __init__(self, capacity: int): self.capacity = capacity self.size = 0 self.cache = {} # key: int -> node: _ListNode # 哑节点:head 与 tail 本身不存储数据 self.head = _ListNode() # 最近使用端(MRU) self.tail = _ListNode() # 最久未使用端(LRU) self.head.next = self.tail self.tail.prev = self.head def get(self, key: int) -> int: """若 key 存在,返回值并将其移动到头部标记为最近使用;否则返回 -1。""" if key not in self.cache: return -1 node = self.cache[key] # 访问后需要更新该节点的时效性:先摘除再插到头部 self._move_to_head(node) return node.value def put(self, key: int, value: int) -> None: """插入或更新 key-value。若超出容量,淘汰尾部最久未使用项。""" if key in self.cache: # 更新已有值,并提升为最近使用 node = self.cache[key] node.value = value self._move_to_head(node) return # 新建节点并放入哈希表,同时插到链表头部(最新使用) new_node = _ListNode(key, value) self.cache[key] = new_node self._add_to_head(new_node) self.size += 1 # 若超出容量,淘汰尾部节点(最久未使用) if self.size > self.capacity: removed = self._pop_tail() # 根据节点中存储的 key,从哈希表同步删除映射 del self.cache[removed.key] self.size -= 1 # ------------------------------ # 以下为核心链表操作(均为 O(1)) # ------------------------------ def _remove(self, node: _ListNode) -> None: """将 node 从双向链表中摘除。 指针操作解释: node.prev node node.next 变为 node.prev node.next """ prev_node = node.prev next_node = node.next prev_node.next = next_node next_node.prev = prev_node def _add_to_head(self, node: _ListNode) -> None: """将 node 插入到 dummy head 之后(最近使用位置)。 指针操作解释: head old_first 变为 head node old_first """ node.prev = self.head node.next = self.head.next self.head.next.prev = node self.head.next = node def _move_to_head(self, node:...
AI 评审点评
以下是 AI 评审对该模型输出的点评:
【CLAUDE】这是一个高质量的 LRU 缓存实现。代码完全满足功能要求和性能约束,使用双向链表 + 哈希表实现 O(1) 时间复杂度的 get 和 put 操作。哑节点的使用简化了边界处理,指针操作逻辑清晰。代码符合 PEP 8 规范,注释详尽且有助于理解,测试用例覆盖全面。唯一可优化之处是可以增加更多边界测试用例和精简部分注释,但整体已达到生产级代码标准。 【GEMINI】这是一个教科书级别的 LRU 缓存实现。模型不仅完美达成了所有功能和性能约束,还在代码整洁度、模块化设计以及文档注释方面表现出色。通过辅助方法封装链表操作,使得主逻辑(get/put)非常易读,是高质量的工业级代码示例。 【KIMI】该实现满足了LRU缓存的所有功能要求,使用合适的数据结构,时间复杂度达标。代码结构清晰,命名规范,注释详尽。测试用例覆盖全面,输出结果符合预期。整体上是一个高质量的实现。
进阶难度评测结果
- 得分:95.2 分
- 通过状态:已通过
模型生成产物
以下是该模型针对此任务的实际生成内容:
```python import time from typing import Any, Dict, Optional class _ListNode: """双向链表节点,用于维护缓存项的访问顺序。""" __slots__ = ("key", "value", "expires_at", "prev", "next") def __init__( self, key: Any, value: Any, expires_at: Optional[float] = None, ) -> None: self.key: Any = key self.value: Any = value self.expires_at: Optional[float] = expires_at self.prev: Optional["_ListNode"] = None self.next: Optional["_ListNode"] = None class LRUCache: """ 基于双向链表 + 哈希表实现的 LRU(最近最少使用)缓存,支持 TTL 惰性删除。 数据结构选择原因: 1. 哈希表(dict):提供 O(1) 平均时间复杂度的 key 查找能力,用于快速定位 缓存项对应的链表节点。 2. 双向链表:通过指针操作即可在 O(1) 时间内将任意节点移动到头部(标记为 最近使用)或删除尾部节点(淘汰最久未使用)。相比数组/队列等结构,双向 链表在任意位置的插入与删除均为 O(1),且配合哈希表可直接定位到具体节点。 3. 两者结合:哈希表负责 key → node 的映射,双向链表负责维护使用顺序, 从而实现 get / put 操作的 O(1) 时间复杂度。 """ def __init__(self, capacity: int) -> None: """ 初始化 LRU 缓存。 Args: capacity: 缓存最大容量,必须为正整数。 Raises: TypeError: capacity 不是整数时抛出。 ValueError: capacity 小于等于 0 时抛出。 """ if not isinstance(capacity, int): raise TypeError( f"capacity must be an integer, got {type(capacity).__name__}" ) if capacity bool: """检查节点是否在惰性删除策略下已过期。""" if node.expires_at is None: return False return time.monotonic() >= node.expires_at def _remove_node(self, node: _ListNode) -> None: """将指定节点从双向链中断开。节点必须当前位于链表中。""" prev_node = node.prev next_node = node.next # 使用伪头尾节点保证 prev_node / next_node 不为 None if prev_node is not None: prev_node.next = next_node if next_node is not None: next_node.prev = prev_node def _add_to_head(self, node: _ListNode) -> None: """将节点插入链表头部,表示最近使用(MRU)。""" node.prev = self._head node.next = self._head.next self._head.next.prev = node self._head.next = node def _move_to_head(self, node: _ListNode) -> None: """将已有节点移动到链表头部。""" self._remove_node(node) self._add_to_head(node) def _pop_tail(self) -> Optional[_ListNode]: """移除链表尾部节点(最久未使用,LRU)并返回该节点。""" if self._tail.prev == self._head: return None node = self._tail.prev self._remove_node(node) return node # ----------------- 公开 API ----------------- def get(self, key: Any) -> Optional[Any]:...
AI 评审点评
以下是 AI 评审对该模型输出的点评:
【CLAUDE】这是一个高质量的LRU缓存实现,完全满足所有技术要求。核心功能正确无误,数据结构选择精准且实现高效,代码规范性和工程化水平优秀。特别值得称赞的是:1) 使用伪头尾节点简化链表操作;2) 完整的类型注解和docstring;3) 全面的异常处理和边界条件校验;4) 测试用例覆盖充分。代码展现了扎实的数据结构功底和良好的工程实践能力,可直接用于生产环境。 【GEMINI】这是一份教科书级别的 LRU 缓存实现。开发者不仅完成了所有功能性要求,还在工程化实践上表现出色:采用了 time.monotonic() 确保计时不受系统时间调整影响、通过私有方法解耦了链表操作、提供了完善的异常反馈。虽然任务描述中提到了并发处理,但由于用户具体要求中未列出该项,且 Python 中线程安全通常需要额外的锁机制,目前的单线程实现已完全满足用户输入的所有明确指令。 【KIMI】整体而言,代码实现了LRU缓存的核心功能,包括基本操作、性能优化和并发处理。数据结构的选择和实现基本正确,代码质量也较高。但在数据结构操作的简洁性、命名规范和注释语言方面还有改进空间。
困难难度评测结果
- 得分:89.5 分
- 通过状态:已通过
模型生成产物
以下是该模型针对此任务的实际生成内容:
以下是一个可用于生产环境的线程安全 LRU 缓存实现。设计遵循**精确 LRU**语义,采用 **HashMap + 独占双向链表**方案,以全局 `ReentrantLock` 保证强一致性;同时通过 Builder 模式、锁外加载、驱逐事件锁外触发等策略兼顾生产级可用性。 --- ### 1. 接口与领域模型 ```java package com.example.cache; /** * 缓存顶层契约。所有实现必须拒绝 null key 与 null value, * 语义与 {@link java.util.concurrent.ConcurrentHashMap} 保持一致, * 避免空值歧义及内存泄漏风险。 * * @param 键类型 * @param 值类型 */ public interface Cache { /** * 获取指定 key 对应的 value。 * * 边界条件: * * key 为 null:抛出 NullPointerException,防御恶意/错误调用。 * key 不存在:返回 null。 * * * @param key 键,不允许为 null * @return 值;若不存在则返回 null * @throws NullPointerException 如果 key 为 null */ V get(K key); /** * 存入键值对。若 key 已存在则替换旧值,并将该节点标记为最近使用。 * * 边界条件: * * key 或 value 为 null:抛出 NullPointerException。 * 写入后超出容量/权重限制:触发 LRU 淘汰,可能异步通知监听器。 * * * @param key 键,不允许为 null * @param value 值,不允许为 null * @throws NullPointerException 如果 key 或 value 为 null */ void put(K key, V value); /** * 若 key 不存在,则使用 loader 加载值并写入缓存。 * * 边界条件: * * key 或 loader 为 null:抛出 NullPointerException。 * loader 返回 null:抛出 NullPointerException,防止缓存污染。 * loader 抛出异常:异常直接外抛,不写入缓存(防止缓存穿透脏数据)。 * 并发场景下多个线程同时调用:可能产生冗余加载(惊群),但仅一个线程写入成功。 * * * @param key 键,不允许为 null * @param loader 加载函数,不允许为 null * @return 当前(已存在或新加载)值 * @throws NullPointerException 如果 key、loader 为 null,或 loader 返回 null */ V computeIfAbsent(K key, java.util.function.Function loader); /** * 移除指定 key。 * * 边界条件: * * key 为 null:抛出 NullPointerException。 * key 不存在:返回 null,无副作用。 * * * @param key 键,不允许为 null * @return 被移除的值;若不存在则返回 null * @throws NullPointerException 如果 key 为 null */ V remove(K key); /** 返回当前缓存条目数(精确值,非估计)。 */ int size(); /** 判断缓存是否为空。 */ boolean isEmpty(); /** 清空所有条目,并触发显式移除通知。 */ void clear(); /** 返回不可变的统计快照。 */ CacheStats stats(); } ``` ```java package com.example.cache; /** * 缓存性能统计快照。使用 record 保证不可变性与线程安全发布。 * * @param hitCount 命中次数 * @param missCount 未命中次数 * @param evictionCount 淘汰次数 */ public record CacheStats(long hitCount, long missCount, long evictionCount) { } ``` ```java package com.example.cache; /** * 淘汰原因枚举。用于 {@link RemovalListener}...
AI 评审点评
以下是 AI 评审对该模型输出的点评:
【CLAUDE】这是一个高质量的生产级LRU缓存实现,整体达到了任务要求的各项标准。核心LRU语义正确,线程安全通过全局ReentrantLock保证,接口设计完整。设计决策有充分的「为什么」解释,分层架构清晰,生产级特性(权重、监听器、统计、Builder)完备。并发测试场景设计有针对性,覆盖了链表一致性和驱逐边界两个关键问题。主要改进空间在于:isOverCapacity中maxWeight和capacity的组合判断逻辑存在缺陷(启用权重后数量限制失效);HashMap初始容量计算不够精确;替换通知使用引用比较。总体而言,这是一个接近生产可用的高质量实现,展示了扎实的并发编程和系统设计能力。 【GEMINI】这是一个非常优秀的生产级 LRU 缓存实现。候选人不仅展示了扎实的数据结构功底,还体现了深厚的并发编程经验,尤其是在处理锁粒度优化和回调风险控制方面表现突出。代码结构清晰,文档完备,完全符合资深架构师的职位要求。 【KIMI】整体来看,这段代码是一个高质量的LRU缓存实现。它正确地实现了LRU的核心功能和线程安全要求,设计上采用了经典的数据结构组合,并考虑了内存优化和生产级健壮性。代码质量较高,结构清晰,注释详细,易于理解和维护。但是,缺少并发测试的具体实现可能会影响代码的健壮性验证。
相关链接
您可以通过以下链接查看更多相关内容: