力扣 - 146. LRU缓存机制
题目
思路
- 利用双链表和HashMap来解题
 - 看到链表题目,我们可以使用头尾结点可以更好进行链表操作和边界判断等
 - 还需要使用size变量来存储双链表的当前长度
 - 调用get,如果存在的话,我们可以调用将在双链表中的结点通过修改指针移动到第一个;如果调用put,我们先判断是否存在该结点,如果不存在,可直接将链接插入即可,同时size++,如果存在的话,先删除原来的结点,再将新结点push到头部即可
 
代码
class LRUCache {
    class Node {
        int key;
        int val;
        Node pre;
        Node next;
        public Node() {}
        public Node(int key, int val) {
            this.key = key;
            this.val = val;
        }
    }
    // 哈希表中的node和双链表的node是同一个结点
    private HashMap<Integer, Node> cache;
    private Node dummyHead;
    private Node dummyTail;
    private int size;
    private int capacity;
    public LRUCache(int capacity) {
        cache = new HashMap<>();
        dummyHead = new Node();
        dummyTail = new Node();
        dummyHead.next = dummyTail;
        dummyTail.pre = dummyHead;
        this.capacity = capacity;
        this.size = 0;
    }
    public int get(int key) {
        // 先获取看看结点存不存在
        Node node = cache.get(key);
        // 如果存在的话,将当前访问的结点移动到链表头,并且返回值
        if (node != null) {
            moveToHead(node);
            return node.val;
        }
        // 不存在的话就返回-1
        return -1;
    }
    public void put(int key, int value) {
        // 也是先看看结点是否存在
        Node node = cache.get(key);
        // 如果存在,那么要做的操作就是将结点移动到链表头,然后更新结点值即可
        if (node != null) {
            node.val = value;
            moveToHead(node);
        } else {
            // 如果不存在的话我们就要创建新结点插入
            Node newNode = new Node(key, value);
            // 先添加到哈希表中
            cache.put(key, newNode);
            // 再添加到链表中
            addToHead(newNode);
            // 并且长度+1
            size++;
            // 因为我们设定最大容量,我们还要判断新put的结点后,容量是否超过了capacity,超过了话,删除最后一个结点,并且长度-1
            if (size > capacity) {
                Node tail = removeTail();
                cache.remove(tail.key);
                size--;
            }
        }
    }
    /**
    * 将node移动到最前面
    */
    private void moveToHead(Node node) {
        if (size > 0 && size <= capacity) {
            remove(node);
            addToHead(node);
        }
    }
    /**
    * 删除node结点
    */
    private void remove(Node node) {
        if (size > 0) {
            node.pre.next = node.next;
            node.next.pre = node.pre;
        }
    }
    /**
    * 删除最后一个结点
    */
    private Node removeTail() {
        if (size > 0) {
            Node node = dummyTail.pre;
            remove(node);
            return node;
        }
        return null;
    }
    /**
    * 添加新结点到第一位去
    */
    private void addToHead(Node node) {
        node.next = dummyHead.next;
        dummyHead.next = node;
        node.next.pre = node;
        node.pre = dummyHead;
    }
}
复杂度分析
- 时间复杂度:\(O(1)\)
 - 空间复杂度:\(O(N)\),其中 N 为初始化的 capacity 容量
 
力扣 - 146. LRU缓存机制的更多相关文章
- 【golang必备算法】 Letecode 146. LRU 缓存机制
		
力扣链接:146. LRU 缓存机制 思路:哈希表 + 双向链表 为什么必须要用双向链表? 因为我们需要删除操作.删除一个节点不光要得到该节点本身的指针,也需要操作其前驱节点的指针,而双向链表才能支持 ...
 - Java实现 LeetCode 146 LRU缓存机制
		
146. LRU缓存机制 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key) - ...
 - 146. LRU 缓存机制  + 哈希表 + 自定义双向链表
		
146. LRU 缓存机制 LeetCode-146 题目描述 题解分析 java代码 package com.walegarrett.interview; /** * @Author WaleGar ...
 - 【力扣】146. LRU缓存机制
		
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key) - 如果关键字 (key) ...
 - [Leetcode]146.LRU缓存机制
		
Leetcode难题,题目为: 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key ...
 - 146. LRU缓存机制
		
题目描述 运用你所掌握的数据结构,设计和实现一个LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key) - 如果密钥 (key ...
 - leetcode:146. LRU缓存机制
		
题目描述: 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key) - 如果密钥 ( ...
 - LeetCode 146. LRU缓存机制(LRU Cache)
		
题目描述 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key) - 如果密钥 (k ...
 - Leetcode 146. LRU 缓存机制
		
前言 缓存是一种提高数据读取性能的技术,在计算机中cpu和主内存之间读取数据存在差异,CPU和主内存之间有CPU缓存,而且在内存和硬盘有内存缓存.当主存容量远大于CPU缓存,或磁盘容量远大于主存时,哪 ...
 
随机推荐
- 带UI 的小初高数学学习系统 —结对编程项目总结
			
一. 项目综述 本系统是基于QT Creator 4.3.0开发环境,开发语言C++,能够实现用户注册,发送短信验证码,用户登陆,用户选择题目类型和数量,显示用户本次答题基本功能.支持对用户账号查重, ...
 - Spring Boot+Spring Security+JWT 实现 RESTful Api 认证(一)
			
标题 Spring Boot+Spring Security+JWT 实现 RESTful Api 认证(一) 技术 Spring Boot 2.Spring Security 5.JWT 运行环境 ...
 - 8-kubernetes-安全
			
kubernetes安全框架 访问K8S集群的资源需要过三关:认证.鉴权.准入控制,任意一个不通过都会失败 普通用户若要安全访问集群API server,往往需要证书.token或者用户名+密码,po ...
 - linux网卡驱动程序架构
			
以cs89x0网卡驱动为例:
 - SpringBoot整合Mybatis 编译失败:找不到符号 程序包不存在
			
问题描述:jpa不好用,转用mybatis,配置多数据源 但是配置后无法编译mvn clean install dao层这些报错,找不到entity的包 问题解决:罪魁祸首:热部署的部分 ...
 - abp(net core)+easyui+efcore实现仓储管理系统——出库管理之三(五十一)
			
abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统--ABP总体介绍(一) abp(net core)+ ...
 - pmm-server 搭建
			
1 搭建docker centos 下 参考文档搭建docker https://www.cnblogs.com/brady-wang/p/11543237.html docker create \ ...
 - Vue企业级优雅实战05-框架开发01-登录界面
			
预览本文的实现效果: # gitee git clone git@gitee.com:cloudyly/dscloudy-admin-single.git # github git clone git ...
 - subprocess中命令为参数序列和字符串的区别
			
参数args 参数args可以是一个参数序列,也可以是一个单独的字符串.参数序列通常是首选的,因为它允许模块处理参数的转义和引号(例如,允许文件名中有空格). 如果传递参数序列,默认情况下,程序执行序 ...
 - JAVA 线上故障排查套路,从 CPU、磁盘、内存、网络到GC 一条龙!
			
线上故障主要会包括cpu.磁盘.内存以及网络问题,而大多数故障可能会包含不止一个层面的问题,所以进行排查时候尽量四个方面依次排查一遍. 同时例如jstack.jmap等工具也是不囿于一个方面的问题的, ...