annotate grok_interview/lru_version2.py @ 65:ecb6ee6a22c3

[Misc] I will no longer drink cool aids of capital P.
author June Park <parkjune1995@gmail.com>
date Wed, 24 Dec 2025 06:22:59 -0800
parents 68fa88ac73fe
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
51
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
1 #
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
2 # Question: Least Recently Used (LRU) Cache Implementation
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
3 #
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
4 # Design and implement a Least Recently Used (LRU) cache. The cache should be initialized with a positive integer capacity.
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
5 #
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
6 # Your implementation must support the following operations with $O(1)$ time complexity for both:
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
7 #
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
8 # get(key): Retrieve the value of the item identified by key. If the key exists, return its value. If it doesn't, return $-1$. This operation also marks the key as the most recently used.
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
9 #
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
10 # put(key, value): Insert or update an item. If the key already exists, update its value and mark it as the most recently used. If the key does not exist, insert the new item. When the cache reaches its capacity, it must evict the least recently used item before inserting the new one.
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
11 #
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
12 # You must use a Hash Map and a Doubly Linked List for the implementation.
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
13
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
14 # Cache , limit 3
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
15
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
16 from typing import Dict
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
17
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
18 # tail.prev.next = node, node.left = tails.prev, tails.prev = Node, node.next = tail
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
19
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
20 # Head <-> Tail
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
21 # Head -> Node <-> Tail ,
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
22 # Head <-> Node <-> Node1 <-> Tail,
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
23 # node.prev.next = node.next, node.next.prev = node.prev
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
24
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
25 class Node:
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
26
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
27 def __init__(self, key: str, value: str):
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
28 self.next: Node | None = None
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
29 self.prev: Node | None = None
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
30 self.key = key
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
31 self.value = value
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
32
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
33 class LRU:
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
34
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
35 def __init__(self, capacity: int = 2):
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
36 self.db: Dict[str, Node] = {}
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
37 self.capacity = capacity
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
38
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
39 self.head = Node("-1", "-1")
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
40 self.tail = Node("-1", "-1")
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
41 self.head.next, self.tail.prev = self.tail, self.head
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
42
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
43 def get(self, key: str):
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
44 node = self.db[key]
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
45 self._remove(node)
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
46 self._add_to_tail(node)
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
47 return node.value
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
48
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
49 def put(self, key: str, value: str):
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
50 if len(self.db) < self.capacity or key in self.db:
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
51 new_node = Node(key, value)
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
52 self._add_to_tail(new_node)
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
53 self.db[key] = new_node
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
54 else:
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
55 least_recently_used_node = self.head.next
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
56 self._remove(least_recently_used_node)
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
57 del self.db[least_recently_used_node.key]
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
58
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
59 new_node = Node(key, value)
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
60 self._add_to_tail(new_node)
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
61 self.db[key] = new_node
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
62
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
63 def _remove(self, node: Node):
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
64 node.prev.next, node.next.prev = node.next, node.prev
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
65
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
66 def _add_to_tail(self, node):
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
67 self.tail.prev.next, node.prev, self.tail.prev, node.next = node, self.tail.prev, node, self.tail
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
68
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
69 lru = LRU()
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
70 lru.put("june", "park")
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
71 lru.put("victor", "sun")
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
72 lru.get("june")
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
73 lru.put("bowen", "sun")
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
74
68fa88ac73fe Interview prep for xAI
June Park <parkjune1995@gmail.com>
parents:
diff changeset
75