[LeetCode]/[Medium]

[Top Interview 150] 146. LRU Cache

위대한먼지 2023. 9. 3. 22:00

Solution)

# Doubly Linked List
class ListNode:
    def __init__(self, key=0, val=0, nextt=None, prev=None):
        self.key = key
        self.val = val
        self.next = nextt
        self.prev = prev


class LRUCache:
    def __init__(self, capacity: int):
        self.capacity = capacity
        self.storage = {}
        self.root = ListNode(0)
        self.tail = self.root


    def put(self, key: int, value: int) -> None:
        newNode = ListNode(key, value)
        self.append(newNode)

        if key in self.storage:
            self.remove(self.storage[key])

        self.storage[key] = newNode
        
        if len(self.storage)-1 == self.capacity:
            del self.storage[self.root.next.key]
            self.remove(self.root.next)


    def get(self, key: int) -> int:
        if key in self.storage:
            updNode = self.storage[key]

            if updNode != self.tail:
                self.remove(updNode)
                self.append(updNode)

            return updNode.val
        
        return -1

    
    # Helper func that removes a node from a list
    def remove(self, node):
        if self.tail == node:
            self.root.next = None
            self.tail = self.root
        else:
            prev = node.prev
            prev.next = node.next
            node.next.prev = prev

    
    # Helper func that appends a node to a list
    def append(self, node):
        self.tail.next = node
        node.prev = self.tail
        self.tail = node
        node.next = None

 

Problem: LeetCode

 

Time Complexity: O(1)

Space Complexity: O(n)

 

Structure of the Code)

Since this problem is more of an exercise problem to practice doubly linked list rather than a complex logic problem, I'll just explain the abstract structure of the code. I think this is a type of question that you have to do it by yourself once you reailze the steps you need to take.

 

To have LRU cache structure, we need a linked list. We need this to constantly update the sequence in O(1) time complexity. Changing the order of nodes in a linked list is not simple but very efficient.

 

We also need a dictionary to get a specific value and a specific node from LRU cache in O(1) time complexity.

 

We're given 2 methods put() and get(). These two methods both require us to include "functions" of removing a specific node from a list and adding a specific node to the tail of a list. So, instead of just copying the same lines over and over again, we'll make two helper functions remove() and append(). 

 

And using these two helper functions, we can fill up the rest of the codes in put() and get(). Just be careful of updating the nodes in the list and the capacity of a dictionary.

 

 

 

This might be the most unhelpful post in this blog, but trust me. It's a lot helpful for you to ACTUALLY code by yourself than me just explaining what/how I did it for this kind of questions.