LeetCode(26), LRU Cache,Least Recently Used Cache

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.

The cache is initialized with a positive capacity.

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

Since this is a key, value pair, we can use a HashMap to store the data. The most important thing is how to select a victim page.

If we use a Queue to trace the order of the pages being used, the search time will be O(n) when we want to renew a page.

If we use a priority queue and a timestamp, every time we pop the smallest value of timestamp, time complexity is O(lgN).

How to achieve O(1) time complexity?
Use a Double linked list, with the head contains the recently used Node, the tail contains the least recently used Node. To quickly find a Node in the double linked list, we can use a hash table to map the key to the reference of its Node. By this way, when we use get(key), find the Node and change its position to head, and when cache is full, just remove the node from tail.

class LRUCache {
    private Node head, tail;
    private int capacity, num;
    private HashMap<Integer, Node> hashMap = new HashMap<>();

    private static class Node {
        private int key, value;
        private Node pre, next;
        Node(int key, int value) {
            this.key = key;
            this.value = value;
        }
    }

    public LRUCache(int capacity) {
        this.capacity = capacity;
        num = 0;
        head = new Node(0, 0);
        tail = new Node(0, 0);
        head.next = tail;
        tail.pre = head;
    }

    // always insert node after head
    private void insert(Node node) {
        node.pre = head;
        node.next = head.next;

        head.next.pre = node;
        head.next = node;
    }

    // remove a node from linked list
    private void remove(Node node) {
        node.pre.next = node.next;
        node.next.pre = node.pre;
    }

    private void moveToFront(Node node) {
        remove(node);
        insert(node);
    }

    private void popTail() {
        remove(tail.pre);
    }

    public int get(int key) {
        Node node = hashMap.get(key);
        if (node == null) return -1;
        moveToFront(node);
        return node.value;
    }

    public void put(int key, int value) {
        Node node = hashMap.get(key);

        if (node == null) {
            node = new Node(key, value);

            if (num < capacity) {
                num++;
                hashMap.put(key, node);
                insert(node);
            }
            else {
                hashMap.put(key, node);
                insert(node);
                hashMap.remove(tail.pre.key);
                popTail();
            }
        }
        else {
            node.value = value;
            moveToFront(node);
        }
    }
}
/**
 * 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);
 */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值