Jerry's Blog

Recording what I learned everyday

View on GitHub


6 November 2019

LeetCode(59) -- 146

by Jerry Zhang

P146. LRU Cache (Medium)

最不常用的内存,如果空间不够用,就把它覆盖掉。

我的思路

内存用map来存数据,然后再用一个queue来保证每次取出来的,都是最不常用的那个。

我的代码

class LRUCache {

    private int capacity;

    private Map<Integer, Integer> cache;

    private Queue<Integer> queue;

    public LRUCache(int capacity) {
        this.capacity = capacity;
        cache = new HashMap<>();
        queue = new LinkedList<>();
    }

    public int get(int key) {
        if (!cache.containsKey(key)) {
            return -1;
        }
        queue.remove(key);
        queue.add(key);
        return cache.get(key);
    }

    public void put(int key, int value) {
        if (cache.containsKey(key)) {
            cache.put(key, value);
            queue.remove(key);
            queue.add(key);
        } else {
            if (cache.size() < capacity) {
                cache.put(key, value);
            } else {
                Integer least = queue.poll();
                cache.remove(least);
                cache.put(key, value);
            }
            queue.add(key);
        }
    }
}

/**
 * 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);
 */

10%

答案

解法1:

class LRUCache extends LinkedHashMap<Integer, Integer>{
    private int capacity;

    public LRUCache(int capacity) {
        super(capacity, 0.75F, true);//三个参数分别是:初始容量、负载因子、是否基于访问排序。
        this.capacity = capacity;
    }

    public int get(int key) {
        return super.getOrDefault(key, -1);
    }

    public void put(int key, int value) {
        super.put(key, value);
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
        return size() > capacity;
    }
}

居然还有这种操作?

HashMap是无序的,当我们希望有顺序地去存储key-value时,就需要使用LinkedHashMap了。

https://www.jianshu.com/p/8f4f58b4b8ab

最优解

class LRUCache {
    //head and tail are dummy nodes
    final Node head= new Node();
    final Node tail = new Node();
    Map<Integer, Node> map;
    int cache_capacity;

    class Node{
        int key;
        int val;
        Node prev;
        Node next;
    }
    public LRUCache(int capacity) {
        map = new HashMap<>(cache_capacity);
        this.cache_capacity = capacity;
        head.next = tail;
        tail.prev = head;
    }

    //add node at the front of the list
    //add this node as the real head
    public void add(Node node){
        Node head_next = head.next;
        head.next = node;
        node.prev = head;
        node.next = head_next;
        head_next.prev = node;
    }

    //add remove the node at the end of the list
    //adding this node as the real tail
    public void remove(Node node){
        Node next_node = node.next;
        Node prev_node = node.prev;
        prev_node.next = next_node;
        next_node.prev= prev_node;
    }

    public int get(int key) {
        int result = -1;
        Node node = map.get(key);
        if(node != null){
            result = node.val;
            remove(node); //most recently used node will be added to front
            add(node);
        }
        return result; //node is null
    }

    //add or override
    public void put(int key, int value) {
        Node node = map.get(key);
        if (node != null){ //already exists
            remove(node); //remove the old node
            node.val = value; //update the value
            //most recenlty used node will be
            //moved to the front, least recently used gets deleted
            add(node);
        } else {
            //first remove the last key
            if (map.size() == cache_capacity){
                map.remove(tail.prev.key); //remove from the tail in the map
                remove(tail.prev); //remove from linkedlist
            }
            Node newNode= new Node();
            newNode.key = key;
            newNode.val = value;
            map.put(key, newNode); //add to map
            add(newNode);//addto lilnkedlist
        }
    }
}

/**
 * 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);
 */

这个就是自己实现了一个双向链表以及linkedHashMap,只实现了有用的方法。

tags: LeetCode