|
21 | 21 | ## Solutions |
22 | 22 |
|
23 | 23 | - [m146 v1.py](<../my-submissions/m146 v1.py>) |
| 24 | +- [m146 v2 proper DLL.py](<../my-submissions/m146 v2 proper DLL.py>) |
24 | 25 | ### Python |
25 | 26 | #### [m146 v1.py](<../my-submissions/m146 v1.py>) |
26 | 27 | ```Python |
@@ -64,3 +65,106 @@ class LRUCache: |
64 | 65 | # obj.put(key,value) |
65 | 66 | ``` |
66 | 67 |
|
| 68 | +#### [m146 v2 proper DLL.py](<../my-submissions/m146 v2 proper DLL.py>) |
| 69 | +```Python |
| 70 | +class DLLNode: |
| 71 | + def __init__( |
| 72 | + self, |
| 73 | + key: int, |
| 74 | + data: int, |
| 75 | + prev_node: Optional['DLLNode'] = None, |
| 76 | + next_node: Optional['DLLNode'] = None |
| 77 | + ): |
| 78 | + self.key = key |
| 79 | + self.data = data |
| 80 | + self.prev = prev_node |
| 81 | + self.next = next_node |
| 82 | + |
| 83 | +class LRUCache: |
| 84 | + def __init__(self, capacity: int): |
| 85 | + self.head = None |
| 86 | + self.tail = None |
| 87 | + self.key2node = {} |
| 88 | + self.cap = capacity |
| 89 | + self.size = 0 |
| 90 | + |
| 91 | + def get(self, key: int) -> int: |
| 92 | + if key not in self.key2node : |
| 93 | + return -1 |
| 94 | + |
| 95 | + output_data = self.pop(key) |
| 96 | + self.append_end(key, output_data) |
| 97 | + return output_data |
| 98 | + |
| 99 | + def put(self, key: int, value: int) -> None: |
| 100 | + if key in self.key2node : |
| 101 | + self.pop(key) |
| 102 | + |
| 103 | + if self.size >= self.cap : |
| 104 | + self.pop() |
| 105 | + |
| 106 | + self.append_end(key, value) |
| 107 | + |
| 108 | + def append_end(self, key: int, data: int) -> None: |
| 109 | + new_node = DLLNode(key=key, data=data, prev_node=self.tail) |
| 110 | + self.key2node[key] = new_node |
| 111 | + self.size += 1 |
| 112 | + |
| 113 | + # this should apply to both if tail and head doesn't exist |
| 114 | + # since if at least one node exists, it's both tail and head |
| 115 | + if not self.tail : |
| 116 | + self.head = new_node |
| 117 | + self.tail = new_node |
| 118 | + return |
| 119 | + |
| 120 | + self.tail.next = new_node |
| 121 | + self.tail = new_node |
| 122 | + |
| 123 | + # Default pop last |
| 124 | + def pop(self, key: int = None) -> int : |
| 125 | + if self.size == 0 : |
| 126 | + return -1 |
| 127 | + |
| 128 | + # Pop LFU node by default |
| 129 | + if key is None : |
| 130 | + key = self.head.key |
| 131 | + |
| 132 | + if key not in self.key2node : |
| 133 | + return -1 |
| 134 | + |
| 135 | + self.size -= 1 |
| 136 | + popping_node = self.key2node.pop(key) |
| 137 | + output_data = popping_node.data |
| 138 | + |
| 139 | + # If it was the only node in DLL |
| 140 | + if self.size == 0 : |
| 141 | + self.head = None |
| 142 | + self.tail = None |
| 143 | + return output_data |
| 144 | + |
| 145 | + # if is head |
| 146 | + if popping_node.prev is None : |
| 147 | + self.head = popping_node.next |
| 148 | + if self.head is not None : |
| 149 | + self.head.prev = None |
| 150 | + return output_data |
| 151 | + |
| 152 | + # if is tail |
| 153 | + if popping_node.next is None : |
| 154 | + self.tail = popping_node.prev |
| 155 | + if self.tail is not None : |
| 156 | + self.tail.next = None |
| 157 | + return output_data |
| 158 | + |
| 159 | + # Regular node |
| 160 | + prev_node, next_node = popping_node.prev, popping_node.next |
| 161 | + prev_node.next, next_node.prev = next_node, prev_node |
| 162 | + return output_data |
| 163 | + |
| 164 | + |
| 165 | +# Your LRUCache object will be instantiated and called as such: |
| 166 | +# obj = LRUCache(capacity) |
| 167 | +# param_1 = obj.get(key) |
| 168 | +# obj.put(key,value) |
| 169 | +``` |
| 170 | + |
0 commit comments