Orivel Orivel
メニューを開く

Least Recently Used (LRU) キャッシュの実装

このプログラミングベンチマークに対する各AIの回答と比較結果を確認できます。

いいね・お気に入り機能を使うにはログインまたは新規登録が必要です。 新規登録

X f L

目次

お題概要

比較ジャンル

プログラミング

お題作成モデル

回答モデル

採点モデル

お題本文

LRU(Least Recently Used)キャッシュクラスをPythonで実装してください。以下の操作をサポートする必要があります。 1. `LRUCache(capacity)` — キャッシュを正の整数容量で初期化します。 2. `get(key)` — キーが存在する場合は、それに関連付けられた値を返します。存在しない場合は -1 を返します。キーにアクセスすると、そのキーが最近使用されたものとしてマークされます。 3. `put(key, value)` — キーと値のペアを挿入または更新します。挿入後にキャッシュが容量を超えた場合、最も最近使用されていないキーを削除します。 `get` と `put` の両方...

さらに表示

LRU(Least Recently Used)キャッシュクラスをPythonで実装してください。以下の操作をサポートする必要があります。 1. `LRUCache(capacity)` — キャッシュを正の整数容量で初期化します。 2. `get(key)` — キーが存在する場合は、それに関連付けられた値を返します。存在しない場合は -1 を返します。キーにアクセスすると、そのキーが最近使用されたものとしてマークされます。 3. `put(key, value)` — キーと値のペアを挿入または更新します。挿入後にキャッシュが容量を超えた場合、最も最近使用されていないキーを削除します。 `get` と `put` の両方は、平均 O(1) の時間計算量で実行される必要があります。 完全で自己完結したPython実装を提供してください。`functools.lru_cache` または `collections.OrderedDict` を使用しないでください。基盤となるデータ構造(例:双方向連結リストとハッシュマップ)を自分で実装する必要があります。 クラス定義の後、容量 2 の `LRUCache` を作成し、以下の操作を実行して、各 `get` の結果を印刷する短いデモンストレーションを含めてください。 ``` cache = LRUCache(2) cache.put(1, 10) cache.put(2, 20) print(cache.get(1)) # 期待値: 10 cache.put(3, 30) # キー 2 を削除 print(cache.get(2)) # 期待値: -1 cache.put(4, 40) # キー 1 を削除 print(cache.get(1)) # 期待値: -1 print(cache.get(3)) # 期待値: 30 print(cache.get(4)) # 期待値: 40 ```

採点方針

優れた回答は、LRUキャッシュの完全で実行可能なPython実装を提供し、以下のすべての基準を満たす必要があります。(1) OrderedDictまたはfunctools.lru_cacheを使用しないこと。(2) 通常、ハッシュマップと双方向連結リストを組み合わせて、getとputの両方で平均O(1)の時間を達成すること。(3) クラスが容量制限を正しく処理し、最も最近使用されていないエントリを削除すること。(4) デモンストレーションコードが含まれており、期待される出力(10、-1、-1、30、40)を生成すること。(5) コードはクリーンで、構造化されており、 reasonably commented または自己説明的であること。部分的な正解でも、軽微な問題がある場合は、部分点を与える可能性があります。OrderedDictを使用したり、O(1)の計算量を達成できなかったりするソリューションは、低く評価されます。デモンストレーションで誤った結果を生成するバグがあるソリューションは、大幅に低く評価されます。

回答

class _Node: __slots__ = ("key", "value", "prev", "next") def __init__(self, key=None, value=None): self.key = key self.value = value self.prev = None self.next = None class LRUCache: def __init__(self, capacity: int): if not isinstance(capacity, int) or capacity <= 0: raise ValueError("capacity must be a positive integer") self.capacity = capacity self.map = {} # key -> _Node # Dummy head/tail to avoid edge cases. # Most-recent is right after head. Least-recent is right before tail. self.head = _Node()...

全文を表示

class _Node: __slots__ = ("key", "value", "prev", "next") def __init__(self, key=None, value=None): self.key = key self.value = value self.prev = None self.next = None class LRUCache: def __init__(self, capacity: int): if not isinstance(capacity, int) or capacity <= 0: raise ValueError("capacity must be a positive integer") self.capacity = capacity self.map = {} # key -> _Node # Dummy head/tail to avoid edge cases. # Most-recent is right after head. Least-recent is right before tail. self.head = _Node() self.tail = _Node() self.head.next = self.tail self.tail.prev = self.head def _add_to_front(self, node: _Node) -> None: node.prev = self.head node.next = self.head.next self.head.next.prev = node self.head.next = node def _remove(self, node: _Node) -> None: node.prev.next = node.next node.next.prev = node.prev node.prev = None node.next = None def _move_to_front(self, node: _Node) -> None: self._remove(node) self._add_to_front(node) def _evict_lru(self) -> None: lru = self.tail.prev if lru is self.head: return self._remove(lru) del self.map[lru.key] def get(self, key: int) -> int: node = self.map.get(key) if node is None: return -1 self._move_to_front(node) return node.value def put(self, key: int, value: int) -> None: node = self.map.get(key) if node is not None: node.value = value self._move_to_front(node) return new_node = _Node(key, value) self.map[key] = new_node self._add_to_front(new_node) if len(self.map) > self.capacity: self._evict_lru() # Demonstration cache = LRUCache(2) cache.put(1, 10) cache.put(2, 20) print(cache.get(1)) # Expected: 10 cache.put(3, 30) # Evicts key 2 print(cache.get(2)) # Expected: -1 cache.put(4, 40) # Evicts key 1 print(cache.get(1)) # Expected: -1 print(cache.get(3)) # Expected: 30 print(cache.get(4)) # Expected: 40

判定

1位 | 勝者

勝利票

3 / 3

平均スコア

99
採点モデル Google Gemini 2.5 Pro

総合点

100

総評

この提出物は傑出しています。LRUキャッシュの正確、効率的、かつ高品質な実装をゼロから提供しています。コードは、ハッシュマップと双方向連結リストを組み合わせた古典的かつ最適なアプローチを使用しています。実装は堅牢で、エッジケースを単純化するためのダミーのヘッド/テールノードを備えており、ヘルパーメソッドや型ヒントなどの優れたコーディングプラクティスを示しています。タスクの要件と制約をすべて完全に遵守しています。

採点詳細を表示

正確さ

重み 35%
100

実装は完全に正しいです。O(1)のルックアップのためのハッシュマップと、使用順序を維持するための双方向連結リストをうまく使用しています。`get`、`put`、およびエビクションのロジックは完璧に機能し、提供されたデモンストレーションコードは正確に期待される出力を生成します。

完全性

重み 20%
100

ソリューションは完全に完了しています。自己完結型の`LRUCache`クラス、プライベートな`_Node`ヘルパークラス、およびプロンプトで要求された正確なデモンストレーションコードを提供します。すべての必要な機能が実装されています。

コード品質

重み 20%
100

コード品質は優れています。読みやすさを向上させる、明確で単一責任のヘルパーメソッド(_add_to_front、_removeなど)によって、よく構造化されています。ダミーのヘッド/テールノードの使用は、連結リストのロジックを単純化する洗練されたテクニックです。型ヒント、`__slots__`、および容量に対する入力検証の包含は、強力でプロフェッショナルなコーディングプラクティスを示しています。

実用性

重み 15%
100

ソリューションには高い実用価値があります。基本的で広く使用されているデータ構造の、教科書のように完璧で効率的な実装を提供します。このコードは実際のアプリケーションで使用でき、最初からLRUキャッシュを構築する方法の良いリファレンスとして役立ちます。

指示遵守

重み 10%
100

ソリューションはすべての指示に完全に準拠しています。禁止されているライブラリ(`collections.OrderedDict`など)を使用せずに、LRUキャッシュをゼロから正しく実装しています。コア操作に必要なO(1)の平均時間計算量を達成し、必須のデモンストレーションを含んでいます。

総合点

99

総評

LRUキャッシュの優れた実装です。このソリューションは、ハッシュマップと双方向連結リストを組み合わせて、get および put 操作の両方で O(1) の平均時間計算量を正しく実現しています。コードは禁止されている構文(OrderedDict、functools.lru_cache)を回避し、すべてのエッジケースを適切に処理し、正確に期待される出力を生成します。ダミーのヘッド/テールセンチネルノードの使用は、エッジケースを排除するクリーンなアプローチです。コードはよく構造化されており、メモリ効率のために __slots__ を使用し、入力検証を含み、明確にコメントされています。デモンストレーションは、要求された出力と正確に一致します。

採点詳細を表示

正確さ

重み 35%
100

実装は完全に正しいです。ダミーセンチネルを持つ双方向連結リストは、最近使用されたものを正しく追跡し、get はアクセスされたノードを先頭に移動し、put は挿入と更新の両方のケースを処理し、eviction は tail.prev ノード(LRU)を削除します。すべてのデモンストレーション出力は、期待される値(10、-1、-1、30、40)と一致します。

完全性

重み 20%
100

ソリューションは完全に完了しています。必要なすべてのメソッド(コンストラクタ、get、put)、ヘルパーのプライベートメソッド、_Node クラス、入力検証、およびタスクで指定された完全なデモンストレーションコードを含む LRUCache クラスが含まれています。

コード品質

重み 20%
100

コード品質は優れています。_Node で __slots__ を使用していることは、メモリ効率への配慮を示しています。プライベートヘルパーメソッド(_add_to_front、_remove、_move_to_front、_evict_lru)は、名前が適切で単一の目的を持っています。型ヒントが使用されています。コメントはセンチネルノードの設計を説明しています。コードはクリーンで読みやすいです。

実用性

重み 15%
95

実装は非常に実用的です。意味のあるエラーメッセージを持つ入力検証が含まれており、パフォーマンスのために __slots__ を使用しており、設計は拡張可能です。唯一のマイナーな欠点は、スレッドセーフティを処理していないことですが、それはタスクによって要求されていませんでした。

指示遵守

重み 10%
100

すべての指示が正確に従われています。OrderedDict または functools.lru_cache は使用されておらず、ハッシュマップ + 双方向連結リストを介して O(1) の複雑さが達成されており、基盤となるデータ構造は手動で実装され、タスクからの正確なデモンストレーションコードが正しい期待される出力コメントとともに含まれています。

採点モデル OpenAI GPT-5 mini

総合点

97

総評

この回答は、ハッシュマップと双方向連結リストを使用したLRUキャッシュの、正しく、効率的で、自己完結型のPython実装を提供します。必要なO(1)操作を満たし、容量と追い出しを正しく処理し、期待される出力を印刷する要求されたデモンストレーションが含まれています。コードはクリーンで読みやすいです。マイナーな問題は、小さなスタイルポイント(例:mapという名前は組み込みをシャドウします、docstringがありません)に限定されますが、これらは正しさやパフォーマンスに影響しません。

採点詳細を表示

正確さ

重み 35%
100

ハッシュマップ+双方向連結リストを使用してLRUを正しく実装しています。getとputはO(1)の平均時間で動作し、追い出しロジックは正しく、提供されたデモンストレーションは期待される出力を生成します。

完全性

重み 20%
100

必要なすべての機能が含まれています:容量検証付きコンストラクタ、getとputのセマンティクス、容量を超えた場合のLRU追い出し、OrderedDictまたはfunctools.lru_cacheの使用なし、および要求されたデモンストレーションが含まれています。

コード品質

重み 20%
90

コードはよく構造化され、明確で、リスト操作を簡素化するためにダミーのヘッド/テールを使用しています。メソッドは小さく、集中しています。マイナーなスタイルの問題:'map'という属性名は組み込みをシャドウし、docstringがありませんが、これらは正しさに影響しません。

実用性

重み 15%
90

実装は実用的であり、実際のコードで使用する準備ができています:効率的で、安全(容量を検証)、メモリ効率(__slots__を使用)です。docstringや単体テストなどの小さな追加から恩恵を受けるでしょうが、機能的には完了しています。

指示遵守

重み 10%
100

指示に正確に従っています:禁止されているライブラリを使用せず、必要なデータ構造を自分で実装し、O(1)操作を保証し、期待される印刷結果を含む正確なデモンストレーションを含んでいます。

class Node: def __init__(self, key=0, value=0): self.key = key self.value = value self.prev = None self.next = None class LRUCache: def __init__(self, capacity: int): self.capacity = capacity self.cache = {} # Sentinel head and tail for the doubly linked list self.head = Node() self.tail = Node() self.head.next = self.tail self.tail.prev = self.head def _add_node(self, node): # Add a node right after the head (making it MRU) node.prev = self.head node.next = self.head.next self.hea...

全文を表示

class Node: def __init__(self, key=0, value=0): self.key = key self.value = value self.prev = None self.next = None class LRUCache: def __init__(self, capacity: int): self.capacity = capacity self.cache = {} # Sentinel head and tail for the doubly linked list self.head = Node() self.tail = Node() self.head.next = self.tail self.tail.prev = self.head def _add_node(self, node): # Add a node right after the head (making it MRU) node.prev = self.head node.next = self.head.next self.head.next.prev = node self.head.next = node def _remove_node(self, node): # Remove a node from the linked list prev_node = node.prev next_node = node.next prev_node.next = next_node next_node.prev = prev_node def _move_to_front(self, node): # Remove a node and add it back to the front (MRU) self._remove_node(node) self._add_node(node) def _pop_tail(self): # Remove and return the LRU node (the one just before the tail sentinel) if self.tail.prev == self.head: return None # List is empty lru_node = self.tail.prev self._remove_node(lru_node) return lru_node def get(self, key: int) -> int: if key not in self.cache: return -1 node = self.cache[key] self._move_to_front(node) # Mark as recently used return node.value def put(self, key: int, value: int) -> None: if key in self.cache: node = self.cache[key] node.value = value # Update value self._move_to_front(node) # Mark as recently used else: new_node = Node(key, value) self.cache[key] = new_node self._add_node(new_node) # Add new node to front if len(self.cache) > self.capacity: # Evict LRU item lru_node = self._pop_tail() if lru_node: del self.cache[lru_node.key] # Demonstration cache = LRUCache(2) cache.put(1, 10) cache.put(2, 20) print(cache.get(1)) # Expected: 10 cache.put(3, 30) # Evicts key 2 print(cache.get(2)) # Expected: -1 cache.put(4, 40) # Evicts key 1 print(cache.get(1)) # Expected: -1 print(cache.get(3)) # Expected: 30 print(cache.get(4)) # Expected: 40

判定

2位

勝利票

0 / 3

平均スコア

98
採点モデル Google Gemini 2.5 Pro

総合点

100

総評

LRUキャッシュの、古典的で、正しく、効率的な実装を提供する、優れたソリューションです。コードは非常によく構造化されており、ヘルパーNodeクラスとプライベートメソッドを使用して双方向リンクリストのロジックをカプセル化しており、可読性と保守性が向上しています。O(1)ルックアップのためのハッシュマップと、O(1)更新のための双方向リンクリストを正しく使用しており、タスクのパフォーマンス要件を完全に満たしています。提出物は、標準ライブラリヘルパーの禁止や、要求されたデモンストレーションの包含など、すべての指示を完璧にフォローしており、正しく実行されます。

採点詳細を表示

正確さ

重み 35%
100

実装は完全に正しいです。get、put、evictionのロジックは期待どおりに機能します。ハッシュマップのルックアップ用と、センチネルノードを持つ双方向リンクリストの最近使用履歴追跡用としての使用は、標準的で正しいアプローチです。提供されたデモンストレーションコードは、正確に期待される出力を生成します。

完全性

重み 20%
100

提出物は完了しています。`Node`と`LRUCache`の両方のクラス定義を含む自己完結型ソリューションを提供し、プロンプトで要求された特定のデモンストレーションブロックが含まれています。すべての必須機能が実装されています。

コード品質

重み 20%
100

コード品質は優れています。クリーンで、整理されており、フォローしやすいです。リンクリスト操作のためのプライベートヘルパーメソッドの使用は、素晴らしい設計選択です。変数名は明確であり、センチネルヘッド/テールノードの使用は、nullチェックを回避することでリスト操作ロジックを簡素化する堅牢な手法です。

実用性

重み 15%
100

このソリューションは、LRUキャッシュの標準的で最も効率的な実装であるため、高い実用価値があります。`get`および`put`操作の両方で要求されるO(1)の平均時間計算量を正しく達成しています。これは、そのようなキャッシュが必要な技術面接や実際のアプリケーションで期待されるまさにそのソリューションです。

指示遵守

重み 10%
100

提出物はすべての指示を完璧にフォローしています。禁止されている`functools.lru_cache`または`collections.OrderedDict`を使用せずに、LRUキャッシュをスクラッチから実装しています。指定されたクラスおよびメソッドシグネチャが含まれており、要求どおりの正確なデモンストレーションコードを提供しています。

総合点

98

総評

LRUキャッシュの優れた実装です。このソリューションは、ハッシュマップと組み合わせたセンチネルのヘッド/テールノードを持つ二重リンクリストを正しく使用しており、getとputの両方の操作でO(1)の平均時間計算量を達成しています。コードは、要求されたとおり、OrderedDictやfunctools.lru_cacheを使用していません。すべてのヘルパーメソッドは適切に命名され、論理的に構成されています。デモンストレーションコードは完全であり、期待される出力(10、-1、-1、30、40)を正確に生成します。コードはクリーンで、よくコメントされており、理解しやすいです。軽微な注意点:putがリストが空でないことを確認してから_pop_tailを呼び出すため、_pop_tailのnullチェックはわずかに冗長ですが、無害な防御的なチェックです。

採点詳細を表示

正確さ

重み 35%
100

実装は完全に正しいです。センチネルノードとハッシュマップを持つ二重リンクリストは、O(1)のgetとputを正しく実装しています。エビクションロジックはLRUアイテム(tail.prev)を正しく削除し、ハッシュマップから削除します。デモンストレーションは、期待どおりに正確に10、-1、-1、30、40を生成します。

完全性

重み 20%
100

ソリューションは完全に完了しています。Nodeクラス、必要なすべてのメソッド(コンストラクタ、get、put)を持つLRUCacheクラス、必要なすべてのヘルパーメソッド、およびタスク仕様に正確に一致する完全なデモンストレーションコードが含まれています。

コード品質

重み 20%
95

コードはクリーンで、適切に構造化され、適切にコメントされています。ヘルパーメソッド(_add_node、_remove_node、_move_to_front、_pop_tail)は適切に命名されており、それぞれに短いドキュメント文字列コメントが付いています。唯一の非常に軽微な問題は、_pop_tailにおけるわずかに冗長なNoneチェックですが、これは無害な防御策であり、著しく損なうものではありません。

実用性

重み 15%
95

この実装は非常に実用的で、本番環境に対応しています。既存のキーの更新、容量オーバーフロー時のエビクション、存在しないキーへのアクセスなど、すべてのエッジケースを正しく処理します。センチネルノードの使用により、境界条件が簡素化されます。O(1)の複雑さにより、実際の使用に適しています。

指示遵守

重み 10%
100

すべての指示が正確に従われています。OrderedDictとfunctools.lru_cacheは使用されていません。基盤となるデータ構造は、二重リンクリストとハッシュマップを使用して手動で実装されています。デモンストレーションコードは、期待される値とエビクションに関するコメントを含め、タスクで指定されたものと正確に一致しています。

採点モデル OpenAI GPT-5 mini

総合点

97

総評

ダガーリンクドリストとハッシュマップを使用した、堅牢で正しいLRUキャッシュの実装。getとputはO(1)で実行され、提供されたデモンストレーションは期待される出力を生成します。軽微な欠点:正でない容量に対する明示的な検証がなく、型ヒントの改善が可能です。

採点詳細を表示

正確さ

重み 35%
100

実装は、センチネルのヘッド/テールを使用してLRU順序を正しく維持し、アクセスされたノードを先頭に移動し、既存のキーを更新し、新しいキーを挿入し、容量を超えたときに最も最近使用されていないアイテムをエビクトします。デモンストレーションは期待される結果をもたらします。

完全性

重み 20%
100

必要なすべての機能が実装されています:getとputを持つLRUCacheクラス、手動のダガーリンクドリストとハッシュマップ、正しいエビクションポリシー、およびプロンプトに一致するデモンストレーション。禁止されているライブラリは使用されていません。

コード品質

重み 20%
90

コードは明確で、構造化されており、リスト操作のためのヘルパーメソッドを使用しています。変数名とコメントは記述的です。軽微な改善点:__init__での容量検証、内部メソッドへの型ヒントの追加、公開メソッドのドキュメント文字列の検討。

実用性

重み 15%
90

効率的で実用的なO(1)実装であり、実際のコードで使用できます。典型的なケースをうまく処理します。ゼロまたは負の容量に対する明示的な処理/検証の欠如は、軽微な実用上の欠点です。

指示遵守

重み 10%
100

指示に正確に従っています:OrderedDictまたはfunctools.lru_cacheを使用せず、O(1)操作のためにハッシュマップを備えた手動のリンクドリストを使用し、指定されたデモンストレーションを含めて期待される出力を生成します。

比較結果サマリー

最終順位は、採点者ごとの順位集約(平均順位 + ボルダ方式の同点処理)で決定します。平均点は参考表示です。

採点者数: 3

勝利票

3 / 3

平均点

99
この回答を見る
X f L