美文网首页
LeetCode_146 LRUCache (链表题)

LeetCode_146 LRUCache (链表题)

作者: monkey01 | 来源:发表于2018-11-13 14:30 被阅读41次

题目地址:https://leetcode-cn.com/problems/lru-cache/

题目:

运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put

获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。
写入数据 put(key, value) - 如果密钥不存在,则写入其数据值。当缓存容量达到上限时,它应该在写入新数据之前删除最近最少使用的数据值,从而为新的数据值留出空间。

进阶:

你是否可以在 O(1) 时间复杂度内完成这两种操作?

示例:

LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // 返回  1
cache.put(3, 3);    // 该操作会使得密钥 2 作废
cache.get(2);       // 返回 -1 (未找到)
cache.put(4, 4);    // 该操作会使得密钥 1 作废
cache.get(1);       // 返回 -1 (未找到)
cache.get(3);       // 返回  3
cache.get(4);       // 返回  4

试题分析:

这道题考察的是链表的一个综合应用,LRU算法大家都知道,核心思想就是当LRUCache中命中的时候返回该值,并将该值移到LRU链表的头节点,如果没有命中返回异常值;在向LRUCache中put值时需要判断Cache中有没有该值,如果已经有了则返回该值并将该值放到链表头,如果没有该值则要判断链表有没有满,如果链表已满则删除链表尾的节点再将新节点插入链表头,如果链表未满则直接插入到链表头。

整个过程听起来不难,不过在实现过程中,光有一个LRU链表的话实现起来没法做到O(1),我们都知道在链表中查找值是O(n)的时间复杂度,无法做到O(1),这里就需要借助于一个HashMap,将链表中所有的cache节点都放在HashMap中,在每次对LRUCache进行操作的时候都需要先通过HashMap进行判断在cache中是否已经包含该值,HashMap的随机读时间复杂度是O(1)。具体代码逻辑可以直接看下面代码实现,逻辑就是上面提到的算法思路。

代码:

public class LRUCache_146 {
    private List<CacheNode> cacheList;
    private Map<Integer, CacheNode> cacheMap;
    private int capacity;

    public LRUCache_146(int capacity) {
        cacheList = new LinkedList<CacheNode>();
        cacheMap = new HashMap<Integer, CacheNode>(capacity);
        this.capacity = capacity;
    }

    public int get(int key) {
        if(cacheMap.containsKey(key)){
            cacheList.remove(cacheMap.get(key));
            cacheList.add(0, cacheMap.get(key));
            return cacheMap.get(key).value;
        }else{
            return -1;
        }
    }

    public void put(int key, int value) {
        if(cacheMap.containsKey(key)){
            cacheList.remove(cacheMap.get(key));
            cacheList.add(0, cacheMap.get(key));
        }else{
            //如果cache中没有该值则插入
            if(cacheMap.size()==capacity){
                //cache已满则需要先删除末尾节点再将新值插入队头
                cacheMap.remove(cacheList.get(cacheList.size()-1).key);
                cacheList.remove(cacheList.size()-1);
                CacheNode node = new CacheNode(key,value);
                cacheMap.put(key, node);
                cacheList.add(0, node);
            }else{
                CacheNode node = new CacheNode(key,value);
                cacheMap.put(key, node);
                cacheList.add(0, node);
            }
        }
    }

    private class CacheNode{
        int key;
        int value;
        public CacheNode(int key, int value){
            this.key = key;
            this.value = value;
        }
    }
}

源码路径:com.monkey01.linkedlist.LRUCache_146

配套测试代码路径:test目录com.monkey01.linkedlist.LRUCache_146Test

https://github.com/feiweiwei/LeetCode4Java.git

相关文章

网友评论

      本文标题:LeetCode_146 LRUCache (链表题)

      本文链接:https://www.haomeiwen.com/subject/gpflfqtx.html