146. LRU缓存机制

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

获取数据 get(key) - 如果关键字 (key) 存在于缓存中,则获取关键字的值(总是正数),否则返回 -1。

写入数据 put(key, value) - 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字/值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。

进阶:

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

示例:

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

solution1

//调用Java底层的LinkedHashMap实现LRU
class LRUCache {
private int cap;
private LinkedHashMap<Integer,Integer> cache = new LinkedHashMap<>();
public LRUCache(int capacity) {
this.cap = capacity;
} public int get(int key) {
if (!cache.containsKey(key)){
return -1;
}
makeRecently(key);
return cache.get(key); } public void put(int key, int value) {
if (cache.containsKey(key)){
cache.put(key,value);
makeRecently(key);
return;
}
if (cache.size() >= cap){
//获取链表头(map->set->Interator->取第一个元素)
int headKey = cache.keySet().iterator().next();
cache.remove(headKey);
}
cache.put(key,value);
}
//移到链表尾
private void makeRecently(int key){
int value = cache.get(key);
cache.remove(key);
cache.put(key,value);
}
}

solution2

public class LRUCache {
//链表节点
class Node{
public int key, val;
public Node next, prev;
public Node(int k, int v){
this.key = k;
this.val = v;
}
}
private Map<Integer,Node> cache = new HashMap<>();
private int size;
private int cap;
private Node head,tail;
public LRUCache(int capacity) {
this.size = 0;
this.cap = capacity;
//使用头尾虚拟节点
head = new Node(0,0);
tail = new Node(0,0);
head.next = tail;
tail.prev = head;
}
// 获取元素,从cache中获得val,node移到链表头
public int get(int key){
Node node = cache.get(key);
if(node == null){
return -1;
}
moveToHead(node);
return node.val;
}
public void put(int key, int value){
Node node = cache.get(key);
if(node == null){
//新建节点插入
Node newNode = new Node(key,value);
cache.put(key,newNode);
addToHead(newNode);
size++;
if (size>cap){
Node overNode = removeTail();
cache.remove(overNode.key);
size--;
}
}else{
//重新赋值节点,移到表头
node.val = value;
moveToHead(node);
}
}
private void addToHead(Node node){
node.prev = head;
node.next = head.next;
head.next.prev = node;
head.next = node;
}
private void moveToHead(Node node){
removeNode(node);
addToHead(node);
}
private void removeNode(Node node){
node.prev.next = node.next;
node.next.prev = node.prev;
}
private Node removeTail(){
Node node = tail.prev;
removeNode(node);
return node;
}
} //思路1:deque 记录cache顺序,map存取键值对
//思路2:哈希链表 使用LinkedHashMap构建
//思路3:手写双向链表 + HashMap 》put时检查,map是否存在,重新赋值或新增,链表新增。get时从map获取,链表移到最前面

LeetCode LRU缓存机制的更多相关文章

  1. leetcode LRU缓存机制(list+unordered_map)详细解析

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

  2. [Leetcode]146.LRU缓存机制

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

  3. Java实现 LeetCode 146 LRU缓存机制

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

  4. 【力扣】146. LRU缓存机制

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

  5. 常见面试题之操作系统中的LRU缓存机制实现

    LRU缓存机制,全称Least Recently Used,字面意思就是最近最少使用,是一种缓存淘汰策略.换句话说,LRU机制就是认为最近使用的数据是有用的,很久没用过的数据是无用的,当内存满了就优先 ...

  6. Q200510-03-03 :LRU缓存机制

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

  7. Q200510-03-02: LRU缓存机制

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

  8. 力扣 - 146. LRU缓存机制

    目录 题目 思路 代码 复杂度分析 题目 146. LRU缓存机制 思路 利用双链表和HashMap来解题 看到链表题目,我们可以使用头尾结点可以更好进行链表操作和边界判断等 还需要使用size变量来 ...

  9. 146. LRU 缓存机制 + 哈希表 + 自定义双向链表

    146. LRU 缓存机制 LeetCode-146 题目描述 题解分析 java代码 package com.walegarrett.interview; /** * @Author WaleGar ...

  10. 【golang必备算法】 Letecode 146. LRU 缓存机制

    力扣链接:146. LRU 缓存机制 思路:哈希表 + 双向链表 为什么必须要用双向链表? 因为我们需要删除操作.删除一个节点不光要得到该节点本身的指针,也需要操作其前驱节点的指针,而双向链表才能支持 ...

随机推荐

  1. 环境搭建:在VSCode搭建Python环境

      1.安装vscode     2.下载python解释器 安装python https://www.python.org/downloads/windows/ 下载可执行的安装文件:   安装完成 ...

  2. 轻松掌握组件启动之MongoDB(上):高可用复制集架构环境搭建

    MongoDB复制集 复制集架构 在生产环境中,强烈不建议使用单机版的MongoDB服务器.原因如下: 单机版的MongoDB无法保证系统的可靠性.一旦进程发生故障或是服务器宕机,业务将直接不可用.此 ...

  3. Splay 详细图解 & 轻量级代码实现

    学 LCT 发现有点记不得 Splay 怎么写,又实在不知道这篇博客当时写了些什么东西(分段粘代码?),决定推倒重写. 好像高一学弟也在学平衡树,但相信大家都比樱雪喵强,都能一遍学会!/kel 写在前 ...

  4. 机器学习实战5-KMeans聚类算法

    概述 聚类 VS 分类 有监督学习 VS 无监督学习 sklearn中的聚类算法 KMeans KMeans参数&接口 n_clusters n_clusters就是KMeans中的K就是告诉 ...

  5. SSL证书链及使用

    什么是证书链 证书链简单来说是域名钥证书.CA公钥.根证书形成的一个颁发链条,属于公钥的一部分. 更白话一点,就是证书链文件包含一系列CA机构公钥的证书. 证书链格式 一般证书链格式是.chain,证 ...

  6. iptables中limit 和 limit-burst 说明

    Limit match    这个匹配操作必须由-m limit明确指定才能使用.有了他的帮助,就能对指定的规则的日志数量加以限制,以免你被信息的洪流淹没哦.比如,你能事先设定一个限定值,当符合条件的 ...

  7. TPshop商城的安装流程(windows)----超详细版

    提前准备 phpStudy下载:https://www.xp.cn/download.html 选择适合自己的版本下载 TPshop商城源文件下载链接:https://pan.baidu.com/s/ ...

  8. 在路上---学习篇(一)Python 数据结构和算法 (4) --希尔排序、归并排序

    独白: 希尔排序是经过优化的插入排序算法,之前所学的排序在空间上都是使用列表本身.而归并排序是利用增加新的空间,来换取时间复杂度的减少.这俩者理念完全不一样,注定造成的所消耗的时间不同以及空间上的不同 ...

  9. 从源码分析 Redis 异步删除各个参数的具体作用

    以前对异步删除几个参数的作用比较模糊,包括网上的很多资料都是一笔带过,语焉不详. 所以这次从源码(基于 Redis 7.0.5)的角度来深入分析下这几个参数的具体作用: lazyfree-lazy-u ...

  10. MySQL锁粒度是什么意思?MySQL锁粒度是什么?

    MySQL锁粒度就是我们通常所说的锁级别.数据库引擎具有多粒度锁定,允许一个事务锁定不同类型的资源. MySQL数据库有三种锁的级别,分别是:页级锁.表级锁 .行级锁. 锁粒度 锁粒度就是我们通常所说 ...