[JavaScript 刷题] 链表 - LRU 缓存, leetcode 146
Posted GoldenaArcher
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[JavaScript 刷题] 链表 - LRU 缓存, leetcode 146相关的知识,希望对你有一定的参考价值。
[javascript 刷题] 链表 - LRU 缓存, leetcode 146
github repo 地址: https://github.com/GoldenaArcher/js_leetcode,Github 的目录 大概 会更新的更勤快一些。
题目地址:146. LRU Cache
题目
如下:
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 sizecapacity
.int get(int key)
Return the value of the key if thekey
exists, otherwise return-1
.void put(int key, int value)
Update the value of the key if thekey
exists. Otherwise, add thekey-value
pair to the cache. If the number of keys exceeds thecapacity
from this operation, evict the least recently used key.The functions
get
andput
must each run inO(1)
average time complexity.
解题思路
这道题有这么两个限制:
- 删除的数据是最近没有操作过的数据
- 操作的时间复杂度为 O ( 1 ) O(1) O(1)
看到 O ( 1 ) O(1) O(1) 的操作时间第一个反应应该就是使用 hashtable 了,这题的两种解法都需要使用到 hashable。
Ordered Map
对于使用 JavaScript 解题,这个操作相对而言比较简单一点,毕竟 JavaScript 内置的 Map 就是 Ordered Map。其操作过程和操作原理是:
-
每一次改查数据时,将原本的数据删除,并且重新添加到 map 中
-
在当前数组到达
capacity
时,删除 map 中的第一个元素Ordered Map 的优势就在于,他迭代的顺序是按照添加的顺序进行的,因此可以完成这个需求
Hashmap + Doubly Linkedlist
这个解法里,hashmap 中的值存储的为结点,每次在操作过当前元素后,将该结点移到链表的头部。每次删除时删除链表尾部的结点。
以提供的 Example1 为例,流程如下:
-
两个 put 插入数据
-
get 一下 1,这样 1 就需要被修改到链表的头部
断开 1, 2 和 tail 之间的连接,将 tail 和 2 连在一起
同样,断开 head 和 2 之间的联系,将 1 放置在 head 后
-
插入新的结点 4
最后操作的是 2,因此需要删除 2 这个结点,将 4 放在 tail 前
-
重复类似操作
使用 JavaScript 解题
Ordered Map 解法
这个可以使用内置 API,代码量就会小很多。
var LRUCache = function (capacity)
this.capacity = capacity;
this.cache = new Map();
;
LRUCache.prototype.get = function (key)
const val = this.cache.get(key);
if (val === undefined) return -1;
this.cache.delete(key);
this.cache.set(key, val);
return val;
;
LRUCache.prototype.put = function (key, value)
this.cache.delete(key);
this.cache.set(key, value);
if (this.cache.size > this.capacity)
for (const [key, _] of this.cache)
this.cache.delete(key);
break;
;
Hashmap + Doubly Linkedlist 解法
这个相当于自己重新写了一个数据结构了,用 JavaScript 实现起来就特别的麻烦。不过 Java 内置 doubly linkedlist,如果这道题用 Java 的话会方便很多。
class Node
constructor(key, val)
this.key = key;
this.val = val;
this.prev = null;
this.next = null;
class DLL
constructor()
this.head = new Node(-1, -1);
this.tail = new Node(-1, -1);
this.head.next = this.tail;
this.tail.prev = this.head;
print()
let l1 = this.head;
let res = [];
while (l1?.next)
res.push(l1?.val, "<->");
l1 = l1.next;
res.push(l1?.val);
console.log(res.join(" "));
appendToHead(node)
const next = this.head.next;
this.head.next = node;
node.next = next;
next.prev = node;
node.prev = this.head;
deleteNode(node)
node.prev.next = node.next;
node.next.prev = node.prev;
moveToHead(node)
this.deleteNode(node);
this.appendToHead(node);
removeTail()
const node = this以上是关于[JavaScript 刷题] 链表 - LRU 缓存, leetcode 146的主要内容,如果未能解决你的问题,请参考以下文章
[JavaScript 刷题] 链表 - 链表的中间结点, leetcode 876
[JavaScript 刷题] 链表 - 相交链表, leetcode 160