【Leetcode】146. LRU Cache

133 阅读1分钟

可以用链表 + 哈希表的方法来做。链表的作用是存储key和value,哈希表的作用是存储key和key对应的node的前一个node,这是考虑到删除的情况下,需要知道要删除的node的前一个node。如果用双向链表的话,则直接存储对应的node即可。

具体的方法是,如果要get某个值时,先去哈希表里查这个值有没有,没有直接返回-1,否则得到这个key对应的节点的前一个节点,然后利用这个节点删除掉那个对应的节点,接着在链表尾新建一个对应节点的拷贝,这样就达到了“最近get过的节点都在末尾,最近没get过的节点都在链表头”的效果,一旦到了capacity,就直接把链表头部节点删掉即可。

如果要put某个值时,做法和get类似,也是要先查一下有没有那个key,没有的话直接在表尾加,否则也是把中间那个node删掉再在末尾新建一个拷贝。

import java.util.HashMap;
import java.util.LinkedHashMap;

public class LRUCache {

    // 创立一个单链表节点的class,里面存key和value
    class ListNode {
        int key, val;
        ListNode next;
        
        ListNode(int key, int val) {
            this.key = key;
            this.val = val;
        }
    }
    
    // 需要两个节点来标记链表头和尾,方便删除或添加
    private ListNode dummy, tail;
    // key是cache的key,value是key对应的node的前一个节点(方便对此节点做删除操作)
    private HashMap<Integer, ListNode> map;
    private int capacity;
    
    public LRUCache(int capacity) {
        dummy = new ListNode(0, 0);
        tail = dummy;
        map = new HashMap<>();
        this.capacity = capacity;
    }
    
    public int get(int key) {
    	// 先去哈希表里查有没有这个key,没有就直接返回-1
        ListNode prev = map.get(key);
        if (prev == null) {
            return -1;
        }
        // 接着先在尾处添上一份拷贝
        tail.next = new ListNode(key, prev.next.val);
        // 把这份拷贝覆盖掉哈希表里原有的那个
        map.put(key, tail);
        // 更新tail
        tail = tail.next;
        // 删除掉旧的那个
        prev.next = prev.next.next;
        // 更新旧的那个的next对应的哈希表里的记录
        map.put(prev.next.key, prev);
        
        return tail.val;
    }
    
    public void put(int key, int value) {
    	// 得到旧的node之前的那个node
        ListNode old = map.get(key);
        // 先在尾部新建一份拷贝
        tail.next = new ListNode(key, value);
        map.put(key, tail);
        tail = tail.next;
        // 如果之前已经存在,就将其删掉。注意每次修改链表的时候,都要去更新一下哈希表
        if (old != null) {
            old.next = old.next.next;
            map.put(old.next.key, old);
        }
        
        if (map.size() > capacity) {
            map.remove(dummy.next.key);
            dummy.next = dummy.next.next;
            map.put(dummy.next.key, dummy);
        }
    }
}

  1. 相关链接:(23条消息) 【Leetcode】146. LRU Cache_记录算法的博客-CSDN博客
  2. 相关链接:146. LRU Cache · leetcode