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)
相关推荐
潇洒畅想2 分钟前
1.1 从∑到∫:用循环理解求和与累积
java·数据结构·python·算法
郝学胜-神的一滴32 分钟前
[简化版 GAMES 101] 计算机图形学 04:二维变换上
c++·算法·unity·godot·图形渲染·unreal engine·cesium
ZC跨境爬虫32 分钟前
海南大学交友平台开发实战day7(实现核心匹配算法+解决JSON请求报错问题)
前端·python·算法·html·json
计算机安禾37 分钟前
【数据结构与算法】第41篇:图论(五):拓扑排序与关键路径
c语言·数据结构·c++·算法·图论·visual studio
Q741_14739 分钟前
每日一题 力扣 1320. 二指输入的的最小距离 动态规划 C++ 题解
c++·算法·leetcode·动态规划
wfbcg1 小时前
每日算法练习:LeetCode 76. 最小覆盖子串 ✅
算法·leetcode·职场和发展
Wect1 小时前
LeetCode 149. 直线上最多的点数:题解深度剖析
前端·算法·typescript
qianpeng8971 小时前
运动声源的到达结构仿真
算法
费曼学习法1 小时前
线段树:区间查询的"终极武器",一文看透高效范围统计
算法
wayz111 小时前
Day 2:线性回归原理与正则化
算法·机器学习·数据分析·回归·线性回归