• 程序员面试金典-面试题 16.25. LRU缓存


    题目:

    设计和构建一个“最近最少使用”缓存,该缓存会删除最近最少使用的项目。缓存应该从键映射到值(允许你插入和检索特定键对应的值),并在初始化时指定最大容量。当缓存被填满时,它应该删除最近最少使用的项目。

    它应该支持以下操作: 获取数据 get 和 写入数据 put 。

    获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。
    写入数据 put(key, value) - 如果密钥不存在,则写入其数据值。当缓存容量达到上限时,它应该在写入新数据之前删除最近最少使用的数据值,从而为新的数据值留出空间。

    示例:

    LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );
    
    cache.put(1, 1);
    cache.put(2, 2);
    cache.get(1);       // 返回  1
    cache.put(3, 3);    // 该操作会使得密钥 2 作废
    cache.get(2);       // 返回 -1 (未找到)
    cache.put(4, 4);    // 该操作会使得密钥 1 作废
    cache.get(1);       // 返回 -1 (未找到)
    cache.get(3);       // 返回  3
    cache.get(4);       // 返回  4

    分析:

    LeetCode 146. LRU CacheLRU缓存机制 (C++/Java)参考这篇讲解。

    程序:

    class LRUCache {
    
        LRUCache(int capacity) {
            this.capacity = capacity;
            this.map = new HashMap<>();
            this.dummyHead = new Node(0, 0);
            this.tail = new Node(0, 0);
    
            dummyHead.prev = null;
            dummyHead.next = tail;
            tail.prev = dummyHead;
            tail.next = null;
        }
        
        int get(int key) {
            if(map.containsKey(key)) {
                Node node = map.get(key);
                int value = node.val;
                removeNode(node);
                addToHead(node);
                return value;
            }
            return -1;
        }
        
        void put(int key, int value) {
            if(map.containsKey(key)){
                Node node = map.get(key);
                removeNode(node);
                map.remove(key);
                size--;
            }
            Node node = new Node(key, value);
            map.put(key, node);
            if(size < capacity) {
                addToHead(node);
                size++;
            }else{
                map.remove(tail.prev.key);
                removeNode(tail.prev);
                addToHead(node);
            }
        }
        private void removeNode (Node node){
            node.prev.next = node.next;
            node.next.prev = node.prev;
        }
        private void addToHead(Node node){
            node.next = dummyHead.next;
            node.next.prev = node;
            dummyHead.next = node;
            node.prev = dummyHead;
        }
        class Node{
            int key;
            int val;
            Node prev;
            Node next;
            public Node(int key, int val){
                this.key = key;
                this.val = val;
            }
        }
        private HashMap<Integer, Node> map;
        private int capacity;
        private Node dummyHead;
        private Node tail;
        private int size;
    }
    
    /**
     * 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);
     */
    class LRUCache {
    
        LRUCache(int capacity) {
            this.capacity = capacity;
            map = new LinkedHashMap<>();
        }
        
        int get(int key) {
            if(map.containsKey(key)) {
                int value = map.get(key);
                map.remove(key);
                map.put(key, value);
                return value;
            }
            return -1;
        }
        
        void put(int key, int value) {
            if(map.containsKey(key)) {
                map.remove(key);
            }
            map.put(key, value);
            if(map.size() > capacity) {
                map.remove(map.keySet().iterator().next());
            }
        }
        private int capacity;
        private LinkedHashMap<Integer, Integer> map;
    }
    
    /**
     * 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);
     */
  • 相关阅读:
    Apollo的Oracle适配改动
    尝试Java,从入门到Kotlin(下)
    尝试Java,从入门到Kotlin(上)
    RabbitMQ权限控制原理
    一文彻底掌握二叉查找树(多组动图)(史上最全总结)
    图解:深度优先搜索与广度优先搜索及其六大应用
    图解:如何理解与实现散列表
    图解:什么是“图”?
    查找算法系列文(一)一文入门二叉树
    线性表(数组、链表、队列、栈)详细总结
  • 原文地址:https://www.cnblogs.com/silentteller/p/12531707.html
Copyright © 2020-2023  润新知