请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache 类:
LRUCache(int capacity)以 正整数 作为容量capacity初始化 LRU 缓存int get(int key)如果关键字key存在于缓存中,则返回关键字的值,否则返回-1。void put(int key, int value)如果关键字key已经存在,则变更其数据值value;如果不存在,则向缓存中插入该组key-value。如果插入操作导致关键字数量超过capacity,则应该 逐出 最久未使用的关键字。
函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。
思路:
由于题目给出的要求是 get和put必须以O(1)的时间复杂度运行 且这个值是键值对的形式,那么自然而然的会想到用hash表之类的结构来实现。
同时需要实现 **逐出** 最久未使用的关键字 考虑使用双向链表实现。
每次get的时候读取值之后将 关键字 放到表头,那么链表的最后一个就是最久未使用的关键字。而双向链表可以方便的读取尾节点而不用遍历整个链表
代码实现如下:
// 链表结构 双向链表好删除尾节点
class Node {
constructor(key = 0, value = 0) {
this.key = key
this.value = value
this.prev = null
this.next = null
}
}
// 初始化 限制最长为capacity
// 创建一个hashmap储存key和node 方便读取
// 创建哨兵节点保证指针永不只指向空
/**
* @param {number} capacity
*/
class LRUCache {
constructor(capacity) {
this.capacity = capacity
// 创建一个哨兵结点 并创建双向链表
this.sentinel = new Node()
this.sentinel.next = this.sentinel
this.sentinel.prev = this.sentinel
this.hashmap = new Map()
}
/**
* 取出node后将其放到链表头
* @param {*} key
* @returns
*/
getNode(key) {
if (!this.hashmap.has(key)) {
return null
}
let node = this.hashmap.get(key)
this.removeNode(node)
this.pushFront(node)
return node
}
/**
* 删除结点
* @param {*} node
*/
removeNode(node) {
node.next.prev = node.prev
node.prev.next = node.next
}
/**
* 把结点添加到链表头 哨兵之后
* @param {*} node
*/
pushFront(node) {
node.prev = this.sentinel
node.next = this.sentinel.next
this.sentinel.next = node
node.next.prev = node
}
/**
* @param {number} key
* @return {number}
*/
get(key) {
let node = this.getNode(key)
return node ? node.value : -1
}
/**
* hash表中查找 如果存在的话就更改值 不存在的话就set进hash表中
* @param {*} key
* @param {*} value
*/
put(key, value) {
let node = this.getNode(key)
if (node) {
node.value = value
return
}
node = new Node(key, value)
this.pushFront(node)
this.hashmap.set(key, node)
if (this.hashmap.size > this.capacity) {
const lastNode = this.sentinel.prev
this.removeNode(lastNode)
this.hashmap.delete(lastNode.key)
}
};
}
/**
* Your LRUCache object will be instantiated and called as such:
* var obj = new LRUCache(capacity)
* var param_1 = obj.get(key)
* obj.put(key,value)
*/