146. LRU Cache

Description

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

Follow up:
Could you do both operations in O(1) time complexity?

Example:

LRUCache cache = new LRUCache( 2 /* capacity */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // returns 1
cache.put(3, 3);    // evicts key 2
cache.get(2);       // returns -1 (not found)
cache.put(4, 4);    // evicts key 1
cache.get(1);       // returns -1 (not found)
cache.get(3);       // returns 3
cache.get(4);       // returns 4

Solution

HashMap + Double-linked-list, time O(1), space O(n)

由于由将节点移到头部的操作,所以单向链表是不够用的,用双向链表就显得很优雅了。

注意get和put都会改变node的优先级,另外put的时候注意检查是否是新添加的节点,如果节点已经存在,注意去掉old mapping。

这道题的细节还挺容易出错的。

class LRUCache {
    private int capacity;
    private Map<Integer, DLL> map;
    private DLL head;
    private DLL tail;
    
    public LRUCache(int capacity) {
        this.capacity = capacity;
        map = new HashMap<>();
        head = new DLL(0, 0);
        tail = new DLL(0, 0);
        head.next = tail;
        tail.prev = head;
    }
    
    public int get(int key) {
        if (!map.containsKey(key)) {
            return -1;
        }
        
        DLL curr = map.get(key);
        remove(curr);
        insertAfterHead(curr);
        
        return curr.val;
    }
    
    public void put(int key, int val) {
        if (map.containsKey(key)) {
            DLL curr = map.get(key);
            curr.val = val;     // update val
            remove(curr);
            insertAfterHead(curr);
        } else {
            if (map.size() == capacity) {   // evict if map is full
                DLL last = evict();
                map.remove(last.key);   // don't forget to remove entry from map
            }
            
            DLL curr = new DLL(key, val);
            map.put(key, curr);
            insertAfterHead(curr);
        }
    }
    // remove p from DLL
    private void remove(DLL p) {
        p.prev.next = p.next;
        p.next.prev = p.prev;
    }
    // insert p after head
    private void insertAfterHead(DLL p) {
        p.next = head.next;
        head.next.prev = p;
        head.next = p;
        p.prev = head;
    }
    // evict last element from DLL
    private DLL evict() {
        DLL last = tail.prev;
        last.prev.next = tail;
        tail.prev = last.prev;
        return last;
    }
    // DLL stores detailed information including key, val and order
    class DLL {
        DLL prev;
        DLL next;
        int key;
        int val;
        
        public DLL(int key, int val) {
            this.key = key;
            this.val = val;
        }
    }
}

/**
 * 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);
 */
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Design and implement a data structure for Least Recently ...
    ShutLove阅读 318评论 0 0
  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi阅读 7,872评论 0 10
  • 今天没有诗,我们不谈诗 和窗棂上的太阳 我们聊聊痛苦 病痛的床 今天没有诗,我们不要叙事 不要再告诉我惊喜 我们刨...
    听风也像是海边的故事阅读 463评论 0 0
  • 我爱秋天 秋天到了.浓郁的桂花迷人最,.醉人香啊我喜欢. 秋天真好啊:满山的枫叶红了。 秋天你真好.你知道什么时候...
    花丹俏阅读 318评论 0 0
  • 今天的安排是瑜伽小小运动馆。妹妹一早起来告诉妈妈腿疼,是大腿的地方,一动就疼,不能动,站不起来了。抱着她坐...
    擎天柱_6e9a阅读 171评论 2 1

友情链接更多精彩内容