-
Notifications
You must be signed in to change notification settings - Fork 90
/
LRU Cache.py
83 lines (68 loc) · 2.21 KB
/
LRU Cache.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
"""
esign and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations:
get and set.
get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it
should invalidate the least recently used item before inserting a new item.
"""
__author__ = 'Daniel'
class Node(object):
def __init__(self, key, val):
self.key = key
self.val = val
self.pre, self.next = None, None
class LRUCache(object):
def __init__(self, capacity):
self.cap = capacity
self.map = {} # key to node
self.head = None
self.tail = None
def get(self, key):
if key in self.map:
cur = self.map[key]
self._elevate(cur)
return cur.val
return -1
def set(self, key, value):
if key in self.map:
cur = self.map[key]
cur.val = value
self._elevate(cur)
else:
cur = Node(key, value)
self.map[key] = cur
self._appendleft(cur)
if len(self.map) > self.cap:
last = self._pop()
del self.map[last.key]
# doubly linked-list operations only
def _appendleft(self, cur):
"""Normal or initially empty"""
if not self.head and not self.tail:
self.head = cur
self.tail = cur
return
head = self.head
cur.next, cur.pre, head.pre = head, None, cur
self.head = cur
def _pop(self):
"""Normal or resulting empty"""
last = self.tail
if self.head == self.tail:
self.head, self.tail = None, None
return last
pre = last.pre
pre.next = None
self.tail = pre
return last
def _elevate(self, cur):
"""Head, Tail, Middle"""
pre, nxt = cur.pre, cur.next
if not pre:
return
elif not nxt:
assert self.tail == cur
self._pop()
else:
pre.next, nxt.pre = nxt, pre
self._appendleft(cur)