1- '''
2- if an item needs to be evicted, the item which was least recently used will be evicted.
3- Both setting or getting a value counts as a use.
4- It should support the following operations. Each operation should have a O(1) worst-case time complexity.
5- * `LruCache(limit)` should construct an LRU cache which never stores more than `limit` entries.
6- * `set(key, value)` should associate `value` with the passed `key`.
7- * `get(key)` should look-up the value previously associated with `key`.
8- '''
91
102class Node :
113 def __init__ (self , key , value ):
12- self .key = key # store the key
13- self .value = value # store the value
14- self .prev = None # previous node in list
15- self .next = None # next node in list
16-
4+ self .key = key
5+ self .value = value
6+ self .previous = None
7+ self .next = None
8+ class LinkedList :
9+ def __init__ (self ):
10+ self .head = None
11+ self .tail = None
12+
13+ # adding a new value in the front of the list
14+ def push_head (self , node ):
15+ node .previous = None
16+ node .next = self .head
17+
18+ if self .head is None : # if list is empty head and tail becomes this node.
19+ self .head = node
20+ self .tail = node
21+ else :
22+ self .head .previous = node
23+ self .head = node
24+
25+ return node # returns the node so we can remove it later
26+
27+ # removing last element
28+ def pop_tail (self ):
29+ if self .tail is None :
30+ raise Exception ("List is empty" )
31+
32+ removed = self .tail
33+ self .remove (removed )
34+ return removed
35+
36+ # removes a specific node
37+ def remove (self , node ):
38+
39+ if node .previous is None : # if removing head
40+ self .head = node .next
41+ else :
42+ node .previous .next = node .next # connect previous to next
43+
44+ if node .next is None : # if removing tail
45+ self .tail = node .previous
46+ else :
47+ node .next .previous = node .previous # connect next to previous
48+ # unplugging node
49+ node .next = None
50+ node .previous = None
1751
1852class LruCache :
19- def __init__ (self , limit ):
20-
53+ def __init__ (self ,limit ) -> None :
54+ if limit <= 0 :
55+ raise ValueError ("Limit must be greater than zero" )
2156 self .limit = limit
22- self .data = {}
23- self .first = None
24- self .last = None
25-
26- def set (self , key , value ):
27-
28- if key in self .data :
29- node = self .data [key ]
30- node .value = value
31-
32- # when node is used, is move to front
33- if node != self .first :
3457
35- if node .prev :
36- node .prev .next = node .next
37- if node .next :
38- node .next .prev = node .prev
39-
40- if node == self .last :
41- self .last = node .prev
42-
43- node .prev = None
44- node .next = self .first
45- self .first .prev = node
46- self .first = node
58+ self .storage = {}
59+ self .order = LinkedList ()
60+ pass
4761
62+ #If key already exists move it to MRU
63+ def touch (self ,node ):
64+ self .order .remove (node )
65+ self .order .push_head (node )
66+
67+ # If we want to add or update a key value pair
68+ def set (self , key , value ):
69+ if key in self .storage :
70+ node = self .storage [key ] #update the value of the key
71+ node .value = value
72+ self .touch (node )
4873 return
49-
50- # create new node when key doesn't exit
51- node = Node (key , value )
52- self .data [key ] = node
53-
54- node .next = self .first
55- if self .first :
56- self .first .prev = node
57- self .first = node
58-
59- if self .last is None :
60- self .last = node
61-
62- # remove last when size is bigger than limit
63- if len (self .data ) > self .limit :
64- old = self .last
65-
66- del self .data [old .key ]
67-
68- self .last = old .prev
69- if self .last :
70- self .last .next = None
71-
72- def get (self , key ):
73-
74- if key not in self .data :
74+
75+ #if we are adding a new key and at our limit
76+ if len (self .storage ) >= self .limit :
77+ lru_node = self .order .pop_tail ()
78+ del self .storage [lru_node .key ]
79+
80+ #insert a new node
81+ new_node = Node (key , value )
82+ self .order .push_head (new_node )
83+ self .storage [key ] = new_node
84+
85+ # updating position to most recently used
86+ def get (self ,key ):
87+ if key not in self .storage :
7588 return None
76-
77- node = self .data [key ]
78-
79- # moving node to front because was used
80- if node != self .first :
81-
82- if node .prev :
83- node .prev .next = node .next
84- if node .next :
85- node .next .prev = node .prev
86-
87- if node == self .last :
88- self .last = node .prev
89-
90- node .prev = None
91- node .next = self .first
92- self .first .prev = node
93- self .first = node
94-
89+ node = self .storage [key ]
90+ self .touch (node )
9591 return node .value
0 commit comments