146 LRU Cache

这是一道hard题,因为Uber群里说面试过,所以做一下题目意思的原型是LRU cache,就是在一定capacity的cache下需要有效的利用空间,把滞留的时间最长没有使用的内存给替换掉,要求取地址和替换替地址的复杂度都是O(1),因此需要HashMap和DoubleLinkedList来实现。

题目中的key 和 value代表了内存地址和存储的数据,这里只用int来表示只是为了简化,因为算法才是真正考察的目的。

HashMap的实现相对简单。DoubleLinkedList就需要自定义Node内,内部有key和value,同时有双端指针。注意了:要写成class,不能是public class

有Node后,在初始化LRUCache时,要初始化两个dummy node,head 和 tail,这是为了方便添加和删除。同时要设计两个方法,remove() 和 addHead(),分别是删除一个node,和在双端链表的头部添加node,有了这两个方法,才真正匹配上DoubleLinkedList的数据结构,从而实现O(1)

还有一个关键点就是,如何track LRU element?起初我只有几个模糊的想法:1,用tag?不太好操作,因为一旦tag的元素被处理过,下一个该tag谁?2,把LRU的元素放在一个固定位置?这样会方便,但是不知道怎么implement,如何实现?看了参考解法,果然是第二种,通过把LRU的element放在doubleLinkedList的头部,就可以解决问题了。。也就是说一直在头部添加处理过的node,那么当capacity到达时,只要删除尾端的node即可,这样就非常巧妙。
总结来说:1,为了get()是O(1),用HashMap;2,为了put()是O(1),需要DoubleLinkedList,通过自己设计一个双端node类来实现。

下面的代码,在写put()的时候,忘记了更新map,这个错误很容易犯,要注意,关于node的任何操作都必须在map和DoubleLinkedList两个DS之间同步进行!


class Node{
    int key;
    int value;
    Node prev;
    Node next;
    
    public Node(int key, int value){
        this.key=key;
        this.value=value;
    }
}

public class LRUCache {
    int capacity;
    HashMap map;
    Node head;
    Node tail;
    int count;
    
    public LRUCache(int capacity) {
        this.capacity=capacity;
        this.count=0;
        map= new HashMap();
        head= new Node(0,0);
        tail= new Node(0,0);
        head.next=tail;
        head.prev=null;
        tail.next=null;
        tail.prev=head;
        
        
    }
    
    public void remove(Node node){
        node.prev.next=node.next;
        node.next.prev=node.prev;
    }

    public void addHead(Node node){
        node.next=head.next;
        head.next.prev=node;
        node.prev=head;
        head.next=node;
    }

    
    public int get(int key) {
        if(map.containsKey(key)){
            int result=map.get(key).value;
            Node target=map.get(key);
            remove(target);
            addHead(target);
            return result;
        }
        else return -1;
    }
    
    public void put(int key, int value) {
        Node target= new Node(key, value);
        if(map.containsKey(key)){
            remove(map.get(key)); // !! do NOT forget to update map
            map.put(key, target); // !! do NOT forget to update map
            addHead(target);
        }
        else{
            if(count


你可能感兴趣的:(Uber实习第一面准备)