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)
相关推荐
程序员小远35 分钟前
软件测试之压力测试详解
自动化测试·软件测试·python·测试工具·职场和发展·测试用例·压力测试
Scc_hy44 分钟前
强化学习_Paper_2000_Eligibility Traces for Off-Policy Policy Evaluation
人工智能·深度学习·算法·强化学习·rl
leke20031 小时前
2025年10月17日
算法
CoovallyAIHub1 小时前
Mamba-3震撼登场!Transformer最强挑战者再进化,已进入ICLR 2026盲审
深度学习·算法·计算机视觉
Aqua Cheng.2 小时前
代码随想录第七天|哈希表part02--454.四数相加II、383. 赎金信、15. 三数之和、18. 四数之和
java·数据结构·算法·散列表
怀揣小梦想2 小时前
跟着Carl学算法--哈希表
数据结构·c++·笔记·算法·哈希算法·散列表
Nebula_g2 小时前
Java哈希表入门详解(Hash)
java·开发语言·学习·算法·哈希算法·初学者
Kent_J_Truman2 小时前
【模拟散列表】
数据结构·算法·蓝桥杯·散列表·常识类
Lchiyu2 小时前
哈希表 | 454.四数相加II 383. 赎金信 15. 三数之和 18. 四数之和
算法
玩镜的码农小师兄2 小时前
[从零开始面试算法] (04/100) LeetCode 136. 只出现一次的数字:哈希表与位运算的巅峰对决
c++·算法·leetcode·面试·位运算·hot100