leetcode 146. LRU Cache (medium)

https://leetcode.com/problems/lru-cache/
题目描述
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

模拟LRU存储过程, 以下是来自维基百科的解释. 总结起来就是当cache满了以后, 把最久未操作的地址内容清空出去, 以放置最新的数据.
Least recently used (LRU)
Discards the least recently used items first. This algorithm requires keeping track of what was used when, which is expensive if one wants to make sure the algorithm always discards the least recently used item. General implementations of this technique require keeping “age bits” for cache-lines and track the “Least Recently Used” cache-line based on age-bits. In such an implementation, every time a cache-line is used, the age of all other cache-lines changes. LRU is actually a family of caching algorithms with members including 2Q by Theodore Johnson and Dennis Shasha, and LRU/K by Pat O’Neil, Betty O’Neil and Gerhard Weikum.

The access sequence for the below example is A B C D E D F.
在这里插入图片描述
LRU working
In the above example once A B C D gets installed in the blocks with sequence numbers (Increment 1 for each new Access) and when E is accessed, it is a miss and it needs to be installed in one of the blocks. According to the LRU Algorithm, since A has the lowest Rank(A(0)), E will replace A.

解题思路

先考虑不使用有序字典, 建立三个列表, cache存放数据, cacheKey存放索引值, evictQ存放地址时序序列, 队首是最久未操作过的地址, 队尾是最新操作过的地址.

本题的核心就是维护一个队列evictQ, 该队列保存的是各个地址的操作时序情况. 每次操作过某一地址的数据 (无论get还是put), 就将当前地址值放入evictQ的队尾. cache满的时候, 弹出队首地址的内容, 放入数据.

get和put操作的时间复杂度都是O(1), 空间复杂的是O(n)

代码

class LRUCache:

    def __init__(self, capacity: int):
        self.cache = [] # 存放数据
        self.cacheKey = [] # 存放索引值
        self.evictQ = [_ for _ in range(capacity)] # the order of evicting  #操作时序队列, 队首是最久未操作过的地址, 队尾是最新操作过的地址
        self.capacity = capacity
        self.used = 0
        
    def get(self, key: int) -> int:
        if key in self.cacheKey:
            index = self.cacheKey.index(key)
            self.evictQ.remove(index)
            self.evictQ.append(index)
            return self.cache[index]
        else:
            return -1
    def put(self, key: int, value: int) -> None:
        # if the key is already in the cache
        if key in self.cacheKey:
            index = self.cacheKey.index(key)
            self.evictQ.remove(index)
            self.evictQ.append(index)
            self.cache[index] = value
        # if the key is not exist
        # 1. if the cache is not full
        # 2. if the cache is full, evict the first of the cache
        else:
            if self.used != self.capacity:
                index = self.evictQ.pop(0)
                self.cacheKey.insert(index, key)
                self.cache.insert(index, value)
                self.evictQ.append(index) # index move to the tail
                self.used += 1
            # 
            elif self.used == self.capacity:
                index = self.evictQ.pop(0) # pop the head in the queue
                self.cacheKey[index] = key
                self.cache[index] = value
                self.evictQ.append(index)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值