LeetCode 146. LRU缓存机制

https://leetcode-cn.com/problems/lru-cache/

这个题在Java可以偷鸡,直接用LinkedHashMap可以直接秒杀

import java.util.LinkedHashMap;
import java.util.Map;

class LRUCache {

    private LinkedHashMap lru;

    public LRUCache(int capacity) {
        lru = new LinkedHashMap(capacity,0.75f,true){
            @Override
            protected boolean removeEldestEntry(Map.Entry eldest) {
                return lru.size() > capacity;
            }
        };
    }

    public int get(int key) {
        if(lru.containsKey(key)) {
            return (int) lru.get(key);
        }else {
            return -1;
        }
    }

    public void put(int key, int value) {
        lru.put(key,value);
    }
}

/**
 * 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);
 */

但是当不用这个Map的时候,我们就要自己手写了。其实LinkedHashMap也是通过一个双向链表来维护了它的插入顺序,我们也可以照猫画虎做一下。

import java.util.HashMap;

public class LRUCache2 { /** * 使用一个双向链表来维护这个map的插入顺序,map的k为输入的key,v为双向链表中的节点。 */ public static class Node { int key; int val; Node next; Node prev; public Node(int key, int val) { this.key = key; this.val = val; } } private HashMap<Integer,Node> lru; private int size; private Node head; private Node tail; public LRUCache2(int capacity) { lru = new HashMap<>(); size = capacity; } public int get(int key) { Node temp = lru.get(key); //如果没有这个key对应的值,说明不存在,返回-1 if(temp == null){ return -1; }else { //说明存在,将它在双向链表的位置插入到最前面。 int res = temp.val; remove(temp); add(temp); return res; } } public void put(int key, int value) { Node temp = lru.get(key); //检查是否存在,如果存在就更新它的值,然后将它从双向链表中放到队头位置。 if(temp != null){ temp.val = value; remove(temp); add(temp); }else { temp = new Node(key,value); //如果已经溢出了,删除队尾的元素 if (lru.size() >= size) { lru.remove(tail.key); remove(tail); } add(temp); lru.put(key,temp); } } /** * 使用头插法,维护双向链表 * @param node */ private void add(Node node){ if(head == null){ head = tail = node; }else { node.next = head; head.prev = node; head = node; } } /** * 移除分三种情况,队列本身只有一个元素,移除的元素在队头、队尾、对中 * @param node */ private void remove(Node node){ if(head == tail){ head = tail = null; }else { if(head == node){ head = head.next; head.prev = null; node.next = null; }else if(node == tail){ tail = tail.prev; tail.next = null; node.prev = null; }else { node.prev.next = node.next; node.next.prev = node.prev; node.prev = null; node.next = null; } } } }

 

双向链表只是拿来维护这个数据的插入顺序,而map中的KV分别是key和对应的结点,结点内含有key和value两个属性。

想这个对应关系真的挺烦的,一开始是直接用LinkedList去做,发现怎么样都没办法将它们两者的关系处理好,只好自己造轮子了

posted @ 2020-05-25 10:49  ZJPang  阅读(171)  评论(0编辑  收藏  举报