分析
题目要求时间复杂度为O(1)
,且最多储存k
个key
梳理下javascript
可用的数据结构:
对象 :
object.create(null)
无法获取最早插入的key
,不能满足超过k
个数就删除数组 :
数组可以满足排序,但是查找和删除的时间复杂度都为
O(n)
我们需要的数据结构是能够记录操作顺序,即可以快速删除,又可以快速查找。
因此可以将双向链表和字典结合使用。
- 构建字典用于存放
ListNode
节点 - 设置双向链表的
head
和tail
set
操作时构建ListNode
节点,并将其放在链表尾部。- 若字典长度超出
k
,则将链表头部数据删除,并删除字典中相应的keydelete cache[key]
- 若字典长度超出
get
操作时根据字典查找到指定ListNode
节点,删除后,再重新插入,执行3操作
题解
方案一:使用双向链表和字典结合实现
class ListNode { prev: ListNode | null; next: ListNode | null; value: any; key: string | number; constructor(key = 0, val = '', prev = null, next = null) { this.value = val || ''; this.prev = prev || null; this.next = next || null; this.key = key; } } class Solution { cache: { [key: string]: ListNode | null }; head: ListNode; tail: ListNode; max = 0; constructor(max: number) { this.cache = {}; this.head = new ListNode(); this.tail = new ListNode(); this.tail.prev = this.head; this.head.next = this.tail; this.max = max; } set(key: string | number, value: any) { if (this.cache.hasOwnProperty(key)) { // 若存在,先删除指定节点,后添加 const node = this.cache[key]; this.remove(node); } const node = new ListNode(key as number, value, null, null); this.addToEnd(node); this.cache[key] = node; if (Object.keys(this.cache).length > this.max) { // 若超出,删除第一个的节点 var fnode = this.head.next; this.remove(fnode); delete this.cache[fnode.key]; } } get(key: string | number) { if (this.cache[key]) { const node = this.cache[key]; this.remove(node); this.addToEnd(node); return node.value; } else { return -1; } } remove(node) { node.prev.next = node.next; node.next.prev = node.prev; } addToEnd(node) { node.prev = this.tail.prev; node.next = this.tail; this.tail.prev.next = node; this.tail.prev = node; } } /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * lru design * @param operators int整型二维数组 the ops * @param k int整型 the k * @return int整型一维数组 */ export function LRU(operators: number[][], k: number): number[] { // write code here const solution = new Solution(k); const result: number[] = []; for (let k = 0; k < operators.length; k++) { const opt = operators[k]; if (opt[0] === 1) { solution.set(opt[1], opt[2]) } else if (opt[0] === 2) { result.push(solution.get(opt[1])); } } return result; }
方案二:使用map数据结构
/** * lru design * @param operators int整型二维数组 the ops * @param k int整型 the k * @return int整型一维数组 */ function LRU( operators , k){ const n = operators.length; const map = new Map(); const res = [] for(let i = 0;i < n;i ++){ if(operators[i][0] === 1){ set(operators[i][1],operators[i][2]); }else{ res.push(get(operators[i][1])); } } function get(key){ const val = map.get(key); if(val === undefined) return -1; map.delete(key); map.set(key,val); return val; } function set(key,val){ if(map.has(key)) map.delete(key); map.set(key,val); if(map.size > k){ map.delete(map.keys().next().value); } } return res; } module.exports = { LRU : LRU };