1+ class DLLNode :
2+ def __init__ (
3+ self ,
4+ key : int ,
5+ data : int ,
6+ prev_node : Optional ['DLLNode' ] = None ,
7+ next_node : Optional ['DLLNode' ] = None
8+ ):
9+ self .key = key
10+ self .data = data
11+ self .prev = prev_node
12+ self .next = next_node
13+
14+ class LRUCache :
15+ def __init__ (self , capacity : int ):
16+ self .head = None
17+ self .tail = None
18+ self .key2node = {}
19+ self .cap = capacity
20+ self .size = 0
21+
22+ def get (self , key : int ) -> int :
23+ if key not in self .key2node :
24+ return - 1
25+
26+ output_data = self .pop (key )
27+ self .append_end (key , output_data )
28+ return output_data
29+
30+ def put (self , key : int , value : int ) -> None :
31+ if key in self .key2node :
32+ self .pop (key )
33+
34+ if self .size >= self .cap :
35+ self .pop ()
36+
37+ self .append_end (key , value )
38+
39+ def append_end (self , key : int , data : int ) -> None :
40+ new_node = DLLNode (key = key , data = data , prev_node = self .tail )
41+ self .key2node [key ] = new_node
42+ self .size += 1
43+
44+ # this should apply to both if tail and head doesn't exist
45+ # since if at least one node exists, it's both tail and head
46+ if not self .tail :
47+ self .head = new_node
48+ self .tail = new_node
49+ return
50+
51+ self .tail .next = new_node
52+ self .tail = new_node
53+
54+ # Default pop last
55+ def pop (self , key : int = None ) -> int :
56+ if self .size == 0 :
57+ return - 1
58+
59+ # Pop LFU node by default
60+ if key is None :
61+ key = self .head .key
62+
63+ if key not in self .key2node :
64+ return - 1
65+
66+ self .size -= 1
67+ popping_node = self .key2node .pop (key )
68+ output_data = popping_node .data
69+
70+ # If it was the only node in DLL
71+ if self .size == 0 :
72+ self .head = None
73+ self .tail = None
74+ return output_data
75+
76+ # if is head
77+ if popping_node .prev is None :
78+ self .head = popping_node .next
79+ if self .head is not None :
80+ self .head .prev = None
81+ return output_data
82+
83+ # if is tail
84+ if popping_node .next is None :
85+ self .tail = popping_node .prev
86+ if self .tail is not None :
87+ self .tail .next = None
88+ return output_data
89+
90+ # Regular node
91+ prev_node , next_node = popping_node .prev , popping_node .next
92+ prev_node .next , next_node .prev = next_node , prev_node
93+ return output_data
94+
95+
96+ # Your LRUCache object will be instantiated and called as such:
97+ # obj = LRUCache(capacity)
98+ # param_1 = obj.get(key)
99+ # obj.put(key,value)
0 commit comments