• [LeetCode] 146. LRU Cache


    题目链接 : https://leetcode-cn.com/problems/lru-cache/

    题目描述:

    运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。

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

    进阶:

    你是否可以在 O(1) 时间复杂度内完成这两种操作?

    示例:

    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
    

    思路:

    思路一:

    使用python里的有序字典OrderedDict

    注释写在代码里, 这个一定要理解, 因为思路二也是这样想的,只不过换了数据结构!

    from collections import OrderedDict
    class LRUCache:
    
        def __init__(self, capacity: int):
            self.maxsize = capacity
            self.lrucache = OrderedDict()
    
        def get(self, key: int) -> int:
            # 说明在缓存中,重新移动字典的尾部
            if key in self.lrucache:
                self.lrucache.move_to_end(key)
            return self.lrucache.get(key, -1)
            
            
    
        def put(self, key: int, value: int) -> None:
            # 如果存在,删掉,重新赋值
            if key in self.lrucache:
                del self.lrucache[key]
            # 在字典尾部添加
            self.lrucache[key] = value
            if len(self.lrucache) > self.maxsize:
                # 弹出字典的头部(因为存储空间不够了)
                self.lrucache.popitem(last = False)
    

    思路二: 哈希 + 双向链表

    也很好理解!

    # 创建双向链表
    class Node:
        def __init__(self, key, val):
            self.key = key
            self.val = val
            self.prev = None
            self.next = None
    
    
    class LRUCache:
    
        def __init__(self, capacity: int):
            # 构建首尾节点, 使之相连
            self.head = Node(0, 0)
            self.tail = Node(0, 0)
            self.head.next = self.tail
            self.tail.prev = self.head
    
            self.lookup = dict()
            self.max_len = capacity
    
        def get(self, key: int) -> int:
            if key in self.lookup:
                node = self.lookup[key]
                self.remove(node)
                self.add(node)
                return node.val
            else:
                return -1
    
        def put(self, key: int, value: int) -> None:
            if key in self.lookup:
                self.remove(self.lookup[key])
            if len(self.lookup) == self.max_len:
                # 把表头位置节点删除(说明最近的数据值)
                self.remove(self.head.next)
            self.add(Node(key, value))
        # 删除链表节点
        def remove(self, node):
            del self.lookup[node.key]
            node.prev.next = node.next
            node.next.prev = node.prev
        # 加在链表尾
        def add(self, node):
            self.lookup[node.key] = node
            pre_tail = self.tail.prev
            node.next = self.tail
            self.tail.prev = node
            pre_tail.next = node
            node.prev = pre_tail
    

    java

    class LRUCache {
    
        Node head = new Node(0, 0), tail = new Node(0, 0);
        Map<Integer, Node> map = new HashMap<>();
        int max_len;
    
        public LRUCache(int capacity) {
            max_len = capacity;
            // 建立双链表
            head.next = tail;
            tail.prev = head;
    
        }
    
        public int get(int key) {
            if (map.containsKey(key)) {
                Node node = map.get(key);
                remove(node);
                add(node);
                return node.value;
            } else
                return -1;
    
        }
    
        public void put(int key, int value) {
            if (map.containsKey(key)) {
                remove(map.get(key));
            }
            // 把表头位置节点删除(说明最近的数据值)
            if (map.size() == max_len) {
                remove(head.next);
            }
            add(new Node(key, value));
    
        }
        // 删除链表
        private void remove(Node node) {
            map.remove(node.key);
            // 删除节点
            node.prev.next = node.next;
            node.next.prev = node.prev;
        }
    
        // 加在链表尾
        private void add(Node node) {
            map.put(node.key, node);
            Node pre_tail = tail.prev;
            node.next = tail;
            tail.prev = node;
            pre_tail.next = node;
            node.prev = pre_tail;
    
        }
    
        // 创建双向链表
        class Node {
            Node prev, next;
            int key, value;
    
            Node(int _key, int _value) {
                key = _key;
                value = _value;
            }
        }
    }
    
  • 相关阅读:
    android adb指令
    android中的4种点击事件
    Android中常用的布局
    String练习
    Java中的String类
    从零开始,搭建一个简单的购物平台(三)
    从零开始,搭建一个简单的购物平台(二)
    从零开始,搭建一个简单的购物平台(一)
    Echarts案例:整一个炫酷一点的仪表盘
    Echarts案例:使用象形柱状图(PictorialBar)实现电池效果柱状图
  • 原文地址:https://www.cnblogs.com/powercai/p/11252619.html
Copyright © 2020-2023  润新知