LeetCode100 LRU缓存思路讲解

思路

这题的关键是同时满足两个要求:

  • O(1) 查找 :所以要用 HashMap。
  • 维护最近使用顺序 :所以要用 双向链表。

只用 HashMap 可以 O(1) 找到 key,但不知道哪个是"最近最少使用"的;

只用链表可以维护顺序,但查找是 O(n)。

所以要把两者结合起来。

数据结构设计

维护一个 双向链表,链表头部表示最近使用的,尾部表示最久未使用的。

同时维护一个 HashMap<Integer, Node>,用来 O(1) 找到某个 key 对应的节点。

  • get(key):

    • 如果 key 不存在,返回 -1。
    • 如果存在,把对应节点移到链表头部,表示最近使用过,然后返回它的值。
  • put(key, value):

    • 如果 key 已存在,更新值,并把节点移到链表头部。
    • 如果 key 不存在:
      • 新建节点,插入链表头部,并放入 map。
      • 如果超过容量,就删除链表尾部节点,同时从 map 中移除。

class LRUCache {

class Node{

int key;

int value;

Node prev;

Node next;

public Node(int key,int value ){

this.key=key;

this.value=value;

}

}

private final int capacity;

private final Map<Integer,Node> map;

private final Node head;

private final Node tail;

public LRUCache(int capacity) {

this.capacity=capacity;

this.map=new HashMap<>();

head=new Node(0,0);

tail=new Node(0,0);

head.next=tail;

tail.prev=head;

}

public int get(int key) {

if(!map.containsKey(key))

return -1;

Node node=map.get(key);

movetohead(node);

return node.value;

}

public void put(int key, int value) {

if(map.containsKey(key)){

Node node=map.get(key);

node.value=value;

movetohead(node);

return;

}

Node node=new Node(key,value);

map.put(key,node);

addtohead(node);

if(map.size()>capacity){

Node lastnode=tail.prev;

removetail();

map.remove(lastnode.key);

return;

}

}

private void addtohead(Node node){

head.next.prev=node;

node.prev=head;

node.next=head.next;

head.next=node;

}

private void removenode(Node node){

node.prev.next=node.next;

node.next.prev=node.prev;

}

private void movetohead(Node node){

removenode(node);

addtohead(node);

}

private Node removetail(){

Node lastnode=tail.prev;

removenode(lastnode);

return lastnode;

}

}

/**

* Your LRUCache object will be instantiated and called as such:

* LRUCache obj = new LRUCache(capacity);

* int param_1 = obj.get(key);

* obj.put(key,value);

*/

相关推荐
专业程序开发源1 小时前
springboot高校学生社团管理系统74810-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·php·课程设计
youdexiang1 小时前
AI 生成会议纪要好用吗?多款 APP 功能分析
java·人工智能·音视频
AC赳赳老秦1 小时前
OpenClaw 与 FineBI 联动方案:公开数据自动采集与实时业务分析看板实践
大数据·开发语言·python·php·finebi·deepseek·openclaw
通信瓦工1 小时前
OCP 冷却环境与冷却剂分配单元(CDU)子项目
java·开发语言
坤坤子吖2 小时前
Python基础语法学习:函数
开发语言·笔记·python·学习
言乐62 小时前
Python体现逻辑回归和决策树的区别
开发语言·python·算法·决策树·逻辑回归
LOVE️YOU2 小时前
Python 类与对象的核心逻辑:从 self、cls 到点号、括号与链式调用
开发语言·python
顶点多余2 小时前
C/C++常见面试题
开发语言·c++
(Charon)2 小时前
【C++面试】右值引用与移动语义:std::move到底做了什么
开发语言·c++