leetcode - 146. LRU Cache

Description

Design a data structure that follows the constraints of a Least Recently Used (LRU) cache.

Implement the LRUCache class:

LRUCache(int capacity) Initialize the LRU cache with positive size capacity.

int get(int key) Return the value of the key if the key exists, otherwise return -1.

void put(int key, int value) Update the value of the key if the key exists. Otherwise, add the key-value pair to the cache. If the number of keys exceeds the capacity from this operation, evict the least recently used key.

The functions get and put must each run in O(1) average time complexity.

Example 1:

复制代码
Input
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
Output
[null, null, null, 1, null, -1, null, -1, 3, 4]

Explanation
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // cache is {1=1}
lRUCache.put(2, 2); // cache is {1=1, 2=2}
lRUCache.get(1);    // return 1
lRUCache.put(3, 3); // LRU key was 2, evicts key 2, cache is {1=1, 3=3}
lRUCache.get(2);    // returns -1 (not found)
lRUCache.put(4, 4); // LRU key was 1, evicts key 1, cache is {4=4, 3=3}
lRUCache.get(1);    // return -1 (not found)
lRUCache.get(3);    // return 3
lRUCache.get(4);    // return 4

Constraints:

复制代码
1 <= capacity <= 3000
0 <= key <= 10^4
0 <= value <= 10^5
At most 2 * 105 calls will be made to get and put.

Solution

dict + heap

Use a dict to store the key-value pair, and also store the timestamp of the calling of functions. If the capacity is exceeded, then pop from the heap, compare the timestamp in heap with timestamp in dict, if they are the same, pop from the dict.

The time complexity of put function is not strictly o ( 1 ) o(1) o(1) though.

dict + double-sided linked list

Use head and tail for the linked list!!

Code

dict + heap

python3 复制代码
class LRUCache:
    import heapq

    def __init__(self, capacity: int):
        self.key_value = {}
        self.time_heap = []
        self.timestamp = 0
        self.capacity = capacity

    def get(self, key: int) -> int:
        if key not in self.key_value:
            return -1
        self.timestamp += 1
        self.key_value[key][1] = self.timestamp
        heapq.heappush(self.time_heap, (self.timestamp, key))
        return self.key_value[key][0]

    def put(self, key: int, value: int) -> None:
        self.timestamp += 1
        self.key_value[key] = [value, self.timestamp]
        heapq.heappush(self.time_heap, (self.timestamp, key))
        while len(self.key_value) > self.capacity:
            timestamp, key = heapq.heappop(self.time_heap)
            if self.key_value[key][1] == timestamp:
                self.key_value.pop(key)       


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

Linked List

python3 复制代码
class LinkedList:
    def __init__(self, key: int, val: int):
        self.key = key
        self.val = val
        self.prev = None
        self.next = None

class LRUCache:

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

    def _remove(self, node) -> None:
        prev = node.prev
        pn = node.next
        prev.next = pn
        pn.prev = prev

    def _add(self, node) -> None:
        self.tail.prev.next = node
        node.prev = self.tail.prev
        self.tail.prev = node
        node.next = self.tail

    def get(self, key: int) -> int:
        if key not in self.key_value:
            return -1
        node = self.key_value[key]
        self._remove(node)
        self._add(node)
        return node.val
        
    def put(self, key: int, value: int) -> None:
        if key in self.key_value:
            self._remove(self.key_value[key])
        node = LinkedList(key, value)
        self._add(node)
        self.key_value[key] = node
        while len(self.key_value) > self.capacity:
            head_next = self.head.next
            self._remove(head_next)
            self.key_value.pop(head_next.key)


# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)
相关推荐
致Great11 小时前
科研人的 AI,不该只回答问题:我用字节TraeWork 跑了一遍真实研究任务
算法
纵有疾風起11 小时前
线性表的定义与基本操作 — 从逻辑结构到 ADT 接口
数据结构·算法·408·线性表·adt
测试_AI_一辰12 小时前
AI Agent 评测最隐蔽的坑-记忆
人工智能·算法·ai·自动化·ai编程
lucas_AI12 小时前
给YOLO检测器插 LoRA,'插对地方'比'插什么'更要命
人工智能·算法
LuminousCPP12 小时前
数据结构-时间与复杂度|时间/空间复杂度 + 两道力扣练习 + 二分查找复盘
c语言·数据结构·经验分享·算法·leetcode
Nil20812 小时前
leetcode 三数之和
数据结构·算法·leetcode
小小龙学IT13 小时前
C++ std::vector 底层实现深度解析:内存布局、扩容策略、移动语义与迭代器失效
开发语言·c++·算法
noipp13 小时前
推荐题目:洛谷 P16689 出征
java·开发语言·数据结构·c++·算法·洛谷·luogu
eBest数字化转型方案13 小时前
从工程视角拆解冰柜资产管理:拍照识别 pipeline、纯净度算法与 IoT 选型踩坑
人工智能·物联网·算法
Interview Aid11213 小时前
Roblox OA 面经|小游戏+编程双修,Coding 两题满分通过
算法