栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java 实现 LRU 算法

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java 实现 LRU 算法

力扣题目:146. LRU 缓存

LRU 是什么?

最近最少使用算法。一个队列,将最近使用的元素放到队列的头部,当队列长度不够时,移除队列的最后一个元素,也就是最近最少使用的元素


解法 1:继承 linkedHashMap

投机取巧解法(最好还是自己实现),利用 Java 的 linkedHashMap 已经实现好的方法,所以直接继承 linkedHashMap 为父类即可。

有兴趣可以自己阅读 linkedHashMap 源码。重点关注这三个方法:

  • afterNodeAccess():访问元素之后,将元素放到双向链表的尾部
  • afterNodeRemoval():删除元素之后,同时将元素也从双向链表中删除
  • afterNodeInsertion():插入元素之后,是否需要移除最近最少使用的元素
class LRUCache extends linkedHashMap {

    
    private int capacity;

    
    public LRUCache(int capacity) {
        super(capacity, 0.75F, true);
        this.capacity = capacity;
    }
    
    
    public int get(int key) {
        return (int) super.getOrDefault(key, -1);
    }
    
    
    public void put(int key, int value) {
        super.put(key, value);
    }

    
    @Override
    public boolean removeEldestEntry(Map.Entry eldest) {
        return super.size() > capacity;
    }
}

解法 2:哈希表 + 双向链表

很重要,面试官需要你写出来的是这个,要能够手写!

class LRUCache {

    
    private int size;

    
    private int capacity;

    
    private Map cache;

    
    private DoublelinkedNode head;

    
    private DoublelinkedNode tail;

    
    public LRUCache(int capacity) {
        this.size = 0;
        this.capacity = capacity;
        this.cache = new HashMap<>();
        this.head = new DoublelinkedNode();
        this.tail = new DoublelinkedNode();
        head.next = tail;
        tail.prev = head;
    }
    
    
    public int get(int key) {
        DoublelinkedNode node = this.cache.get(key);

        // 如果要获取的节点不存在
        if (node == null) {
            return -1;
        }
        // 移动到双向链表头部
        moveToHead(node);
        // 返回值
        return node.value;
    }
    
    
    public void put(int key, int value) {
        DoublelinkedNode node = cache.get(key);
        // 如果元素不存在
        if (node == null) {
            node = new DoublelinkedNode(key, value);
            // 添加到哈希表中
            cache.put(key, node);
            // 双向链表长度加 1
            size++;
            // 添加到双向链表头部
            addToHead(node);
            // 如果长度大于容量,说明要删除元素了
            if (size > capacity) {
                // 从双向链表中删除最后一个元素
                DoublelinkedNode tail = removeTail();
                // 同时从哈希表中删除对应的元素
                cache.remove(tail.key);
                // 长度减 1
                size--;
            }
        // 如果元素存在
        } else {
            // 修改值
            node.value = value;
            // 移动到双向链表头部
            moveToHead(node);
        }
    }

    
    class DoublelinkedNode {

        
        int key;

        
        int value;

        
        DoublelinkedNode prev;

        
        DoublelinkedNode next;

        
        public DoublelinkedNode() {}
        public DoublelinkedNode(int key, int value) {
            this.key = key;
            this.value = value;
        }
    }

    
    private void addToHead(DoublelinkedNode node) {
        node.next = head.next;
        node.prev = head;
        node.next.prev = node;
        head.next = node;
    }

    
    private void removeNode(DoublelinkedNode node) {
        node.next.prev = node.prev;
        node.prev.next = node.next;
        node.prev = null;
        node.next = null;
    }

    
    private void moveToHead(DoublelinkedNode node) {
        removeNode(node);
        addToHead(node);
    }

    
    private DoublelinkedNode removeTail() {
        DoublelinkedNode node = this.tail.prev;
        removeNode(node);
        return node;
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/680682.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号