146. LRU 缓存

参考146. LRU 缓存

题目

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。

实现 LRUCache 类:

  • LRUCache(int capacity)正整数 作为容量 capacity 初始化 LRU 缓存

  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1

  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 getput 必须以 O(1) 的平均时间复杂度运行。

解题思路

  • 哈希表+双向链表:链表的处理细节比较多,需要注意链表指针的变换,使用哈希表作为存储数据结构,要想实现put操作O(1)时间复杂度,需要用双向链表结构存储哈希表里面的prenext节点,链表头指向最久未使用的节点,最近使用的节点放在末尾使用headtail两个节点记录。

哈希表+双向链表

class LRUCache {

    HashMap<Integer,Node> hm = new HashMap<>();
    Node head = null,tail = null;
    int capacity = 0,len = 0;
    public LRUCache(int capacity) {
        this.capacity = capacity;
    }
    
    public int get(int key) {
        if(!hm.containsKey(key)) return -1;
        Node node = hm.get(key);
        if(tail != node) {
            Node pre = node.pre,next = node.next;
            tail.next = node;
            node.pre = tail;
            tail = node;
            if(pre != null){
                pre.next = next;
                next.pre = pre;
            }
            else {
                head = next;
                head.pre = null;
            }
        }
        return node.value;
    }
    
    public void put(int key, int value) {
        if(hm.containsKey(key)){
            Node cur = hm.get(key);
            cur.value = value;
            if(tail != cur){
                Node pre = cur.pre,next = cur.next;
                tail.next = cur;
                cur.pre = tail;
                tail = cur;
                if(pre != null){
                    pre.next = next;
                    next.pre = pre;
                }
                else{
                    head = next;
                    head.pre = null;
                } 
            }
        } 
        else {
            Node cur = null;
            if(len == capacity) { //满了删掉最久未使用的key
                if(head != null) {
                    hm.remove(head.key);
                    Node hnext = head.next;
                    head = hnext;
                    if(head != null)head.pre = null;
                    if(head == tail) tail = null;
                }
                cur = new Node(key,value);
                hm.put(key,cur);//先删除后添加防止内存不足
            }else {
                cur = new Node(key,value);
                hm.put(key,cur);
                len += 1;
                if(len == 1) {
                    head = cur;
                    tail = cur;
                }
            } 
            if(tail != hm.get(key)){
                if(tail != null) tail.next = cur;
                cur.pre = tail;
                tail = cur;
                if(capacity == 1) head = tail;
            }
        }
        
    }

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

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

复杂度分析

  • 时间复杂度:O(1),哈希表的存储和访问都是O(1)
  • 空间复杂度:O(k),kcapacityLRU`容量.
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 146. LRU 缓存[https://leetcode.cn/problems/lru-cache/] 请你设计...
    水中的蓝天阅读 178评论 0 0
  • 前言 缓存是一种提高数据读取性能的技术,在计算机中cpu和主内存之间读取数据存在差异,CPU和主内存之间有CPU缓...
    小码A梦阅读 183评论 0 0
  • 题目描述:运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取...
    简单书写_阅读 370评论 0 0
  • 146. LRU缓存机制(难度:中等) 题目链接:https://leetcode-cn.com/problems...
    一直流浪阅读 674评论 0 3
  • 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 ge...
    放下梧菲阅读 115评论 0 0

友情链接更多精彩内容