zoukankan      html  css  js  c++  java
  • 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去做,发现怎么样都没办法将它们两者的关系处理好,只好自己造轮子了

  • 相关阅读:
    [QT]
    [QT]
    企业内搜索引擎项目(一):架构
    Muduo网络库实战(二):实现服务器与客户端的连接
    Muduo网络库实战(一):安装和配置
    Xapian实战(一):环境搭建 + 简介
    Centos 6.5升级gcc : 源码安装 + rpm安装
    Hadoop学习笔记(二)——插件安装和使用(Hadoop Eclipse)
    Hadoop学习笔记(三) ——HDFS
    Hadoop学习笔记(一)——安装与配置
  • 原文地址:https://www.cnblogs.com/ZJPaang/p/12955613.html
Copyright © 2011-2022 走看看