zoukankan      html  css  js  c++  java
  • leetcode146- LRU Cache- hard

    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
    

    数据结构:DoublyLinkedList+HashMap=LinkedHashMap。Double list是为了可以随便把中间的一个元素放到列表最尾端说明最新;hashMap是为了O(1)找到中间那个元素
    Prev, next, key, value
     
    把旧的放左端,新的放右端,满了删旧的,更新放新的。
    Follow up: 用单向列表也可以,小trick hashMap里value存前一个节点不存当前节点,这样就又能取到前面的又能取到当前的了node, node.next。
     
    细节:
    1.用了几个数据结构,在增删查改时就要保证每个数据结构都被update了!你今天remove的时候只更新了链表忘了更新map了。
    2.这题Node的定义里必须要有key,否则会出现你想删最老结点时,你能根据链表head拿到最老结点,但丢失了它的key无法在map里删掉这条记录,那以后get这个key就都还会返回值回去了。 
     

    实现: 

     
    public class LRUCache {
            /*
             * @param capacity: An integer
             */
    
            private class Node{
                // 必须要有这个!不然你删最老节点的时候,不知道老节点key就不能从map移走这条了!
                public int key;
                public int val;
                public Node prev;
                public Node next;
                public Node(int key, int val) {
                    this.key = key;
                    this.val = val;
                    this.prev = this.next = null;
                }
            }
    
            private int capacity;
            private Map<Integer, Node> mapKeyNode;
            private Node dummyHead;
            private Node dummyTail;
    
            public LRUCache(int capacity) {
                // do intialization if necessary
                this.capacity = capacity;
                this.mapKeyNode = new HashMap<>();
                this.dummyHead = new Node(-1, 100);
                this.dummyTail = new Node(-1, 100);
                this.dummyHead.next = this.dummyTail;
                this.dummyTail.prev = this.dummyHead;
            }
    
            /*
             * @param key: An integer
             * @return: An integer
             */
            public int get(int key) {
                // write your code here
                if (!mapKeyNode.containsKey(key)) {
                    return -1;
                }
                updateKey(key);
                return mapKeyNode.get(key).val;
            }
    
            /*
             * @param key: An integer
             * @param value: An integer
             * @return: nothing
             */
            public void set(int key, int value) {
                // write your code here
                if (mapKeyNode.containsKey(key)) {
                    mapKeyNode.get(key).val = value;
                    updateKey(key);
                    return;
                }
                
                if (mapKeyNode.size() == capacity) {
                    // 切记还要从map里删去!!!两个数据结构那增删查改都是要两边都改的!而且用key去索引不是用val!
                    mapKeyNode.remove(dummyHead.next.key);
                    removeOldestKey();
                }
                Node newNode = new Node(key, value);
                mapKeyNode.put(key, newNode);
                updateKey(key);
            }
    
            private void updateKey(int key) {
                Node node = mapKeyNode.get(key);
                if (node.prev != null) {
                    node.prev.next = node.next;    
                }
                if (node.next != null) {
                    node.next.prev = node.prev;    
                }
                dummyTail.prev.next = node;
                node.prev = dummyTail.prev;
    
                node.next = dummyTail;
                dummyTail.prev = node;
            }
    
            private void removeOldestKey() {
                Node node = dummyHead.next;
                node.prev.next = node.next;
                node.next.prev = node.prev;
                // 这是不是个好习惯?
                node.prev = null;
                node.next = null;
            }
        }
  • 相关阅读:
    单词统计
    学习进度_第十周
    学习进度_第九周
    典型用户、场景分析
    一维数组4.25
    《构建之法》阅读笔记03
    学习进度_第八周
    《构建之法》阅读笔记02
    夏壹队——nabcd
    个人作业阶段二 4
  • 原文地址:https://www.cnblogs.com/jasminemzy/p/7965393.html
Copyright © 2011-2022 走看看