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;
        }
    }

 

posted @ 2017-12-03 09:18  jasminemzy  阅读(140)  评论(0编辑  收藏  举报