【Leetcode】python - [146] LRU Cache 個人解法筆記 (updated: 2022/6/19) #重要題型

題目出處

146. LRU Cache

難度

Medium

個人範例程式碼 - 2022/6/19 二刷

class Node:
    def __init__(self,key, val):
        self.key = key
        self.val = val
        self.next = None
        self.prev = None

class LRUCache:

    def __init__(self, capacity: int):
        self.capacity = capacity
        self.hash = {}
        self.head = Node(-1, -1)
        self.tail = Node(-1, -1)
        self.head.next = self.tail
        self.tail.prev = self.head


    def get(self, key: int) -> int:
        if key not in self.hash:
            return -1
        node = self.hash[key]
        self.remove_node(node)
        self.move_to_tail(node)
        return node.val


    def put(self, key: int, value: int) -> None:
        if self.get(key) != -1: # old key
            self.hash[key].val = value
            return

        # new key
        if len(self.hash) >= self.capacity:
            self.pop_front()
        node = Node(key, value)
        self.move_to_tail(node)
        self.hash[key] = node

    def remove_node(self, node):
        node.prev.next = node.next # remove front-> node
        node.next.prev = node.prev # remove node -> next

    def move_to_tail(self, node):
        node.prev = self.tail.prev # tail.prev <- node
        node.next = self.tail # node -> tail

        node.prev.next = node # tail.prev -> node
        self.tail.prev = node # node <- tail


    def pop_front(self):
        del self.hash[self.head.next.key]
        self.head.next = self.head.next.next
        self.head.next.prev = self.head



# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)

最近在練習程式碼本身就可以自解釋的 Coding style,可以嘗試直接閱讀程式碼理解

算法說明

在標準的解答中,大概念是我們要設計一個 Linked List 配合 hashtable 進行 node 的快速查找,

我們可以把功能進行拆分,大致上我們會需要:

  • get:(取得新元素,題目需要)
  • put:(加入新元素,題目需要)
  • remove_node:移除一個元素 node
  • move_to_tail:將一個元素新增至 tail
  • pop_front:處理當 capacity 滿的時候,將最舊的元素移除

而為了快速且方便的能在 Linked List 中移動,
我們使用雙向的 Linked List,這樣在「查找前面一個元素」時,會非常方便

input handling

此題為程式設計類題目,需要能夠保持不斷的運作
(並非單純輸入一個 testcase 得到一個結果的類型。)

Boundary conditions

此題為程式設計類題目,需要能夠保持不斷的運作
(並非單純輸入一個 testcase 得到一個結果的類型。)

個人範例程式碼 - 2022/5/18 一刷

有解出來,但不是題目要的 (queue + hashtable)

class LRUCache: # recently

    def __init__(self, capacity: int):
        self.capacity = capacity
        self.hashtable = {}
        self.queue = deque()


    def get(self, key: int) -> int:
        if key not in self.queue:
            return -1

        value = self.hashtable[key]
        self.queue.remove(key)
        self.queue.append(key)
        # print(self.queue)

        return value

    def put(self, key: int, value: int) -> None:
        if key in self.queue:
            self.queue.remove(key)
        self.queue.append(key)
        self.hashtable[key] = value

        if len(self.queue) > self.capacity:
            key = self.queue.popleft()
            # del self.hashtable[key]
        # print(self.queue)


# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)

最近在練習程式碼本身就可以自解釋的 Coding style,可以嘗試直接閱讀程式碼理解

算法說明

LRU cache 的設計方式,主要是由 linked list + hashtable

概念就是透過 linked list 保持順序性,而透過 hashtable 去查詢。

input handling

此題為程式設計類題目,需要能夠保持不斷的運作
(並非單純輸入一個 testcase 得到一個結果的類型。)

Boundary conditions

此題為程式設計類題目,需要能夠保持不斷的運作
(並非單純輸入一個 testcase 得到一個結果的類型。)

Reference

Licensed under CC BY-NC-SA 4.0