Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

Follow up:
Could you do both operations in O(1) time complexity?

题意:实现一个LRU缓存

Solution: HashMap + doubly LinkedList

删除操作分为2种情况:

  • 给定node data删除node: 单链表和双向链表都需要从头到尾进行遍历从而找到对应node进行删除,时间复杂度都为O(n)。
  • 给定node address删除node: 单链表需要从头到尾遍历直到找到该node的pre node,时间复杂度为O(n)。双向链表只需O(1)时间即能找到该node的pre node。

HashMap保存node address,可以基本保证在O(1)时间内找到该node

具体实现如下:

put(1,1):   先create 一个newNode(1,1)地址为$Node@435,HashMap存入(1, $Node@435),  双向链表将newNode(1,1)设为head

put(2,2):   先create 一个newNode(2,2)地址为$Node@436,HashMap存入(2, $Node@436),  双向链表将newNode(2,2)设为head

get(1):   先在HashMap中找到1对应node的地址$Node@435,通过该地址找到双向链表对应node(1,1) 。删除该node(1,1)再重新setHead

put(3,3):   先create 一个newNode(3,3)地址为$Node@437, 发现Cache is full! We need to evict something to make room.

1.  首先释放HashMap空间,通过双向链表中tailNode的key找到要在HashMap中删除的key

2.  然后删掉双向链表的tailNode

3.  将newNode(3,3)在双向链表中setHead

思考:

1. why not using java.util.LinkedinList?

因为java自带的linkedlist中,删除操作是从头到尾scan特定值再删除,时间为O(n)。但题目要求O(1)。

2. why not using java.util.LinkedHashMap?
这题说白了,就是考察java自带的LinkedHashMap是怎么实现的,我们当然不能。

code

 public class LRUCache {
private int capacity;
private final HashMap<Integer, Node> map;
private Node head;
private Node tail; public LRUCache(int capacity) {
this.capacity = capacity;
map = new HashMap<>();
} public int get(int key) {
// no key exists
if (!map.containsKey(key)) return -1;
// key exists, move it to the front
Node n = map.get(key);
remove(n);
setHead(n);
return n.value; } public void put(int key, int value) {
// key exits
if (map.containsKey(key)) {
// update the value
Node old = map.get(key);
old.value = value;
// move it to the front
remove(old);
setHead(old);
}
// no key exists
else {
Node created = new Node(key, value);
// reach the capacity, move the oldest item
if (map.size() >= capacity) {
map.remove(tail.key);
remove(tail);
setHead(created);
}
// insert the entry into list and update mapping
else {
setHead(created);
}
map.put(key, created);
}
} private void remove(Node n) {
if (n.prev != null) {
n.prev.next = n.next;
} else {
head = n.next;
}
if (n.next != null) {
n.next.prev = n.prev;
} else {
tail = n.prev;
} } private void setHead(Node n) {
n.next = head;
n.prev = null;
if (head != null) head.prev = n;
head = n;
if (tail == null) tail = head;
} // doubly linked list
class Node {
int key;
int value;
Node prev;
Node next; public Node(int key, int value) {
this.key = key;
this.value = value;
}
}
}

[leetcode]146. LRU CacheLRU缓存的更多相关文章

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

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

  2. leetcode 146. LRU Cache 、460. LFU Cache

    LRU算法是首先淘汰最长时间未被使用的页面,而LFU是先淘汰一定时间内被访问次数最少的页面,如果存在使用频度相同的多个项目,则移除最近最少使用(Least Recently Used)的项目. LFU ...

  3. [LeetCode] 146. LRU Cache 最近最少使用页面置换缓存器

    Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...

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

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

  5. [LeetCode] 146. LRU Cache 近期最少使用缓存

    Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...

  6. LeetCode 146. LRU缓存机制(LRU Cache)

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

  7. Leetcode 146. LRU 缓存机制

    前言 缓存是一种提高数据读取性能的技术,在计算机中cpu和主内存之间读取数据存在差异,CPU和主内存之间有CPU缓存,而且在内存和硬盘有内存缓存.当主存容量远大于CPU缓存,或磁盘容量远大于主存时,哪 ...

  8. Java for LeetCode 146 LRU Cache 【HARD】

    Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...

  9. leetcode@ [146] LRU Cache (TreeMap)

    https://leetcode.com/problems/lru-cache/ Design and implement a data structure for Least Recently Us ...

随机推荐

  1. Centos 的计划任务 crontab

    使用计划任务! crontab命令主要有3个参数: -e :编辑用户的crontab. -l :列出用户的crontab的内容. -r :删除用户的crontab的内容. 执行crontab -e,将 ...

  2. Vue引用其他组件,但组件某些部分不需要时的简单处理

    项目开发时,我们会把多个地方重复使用的模块抽象成组件,提供给大家一起使用,但是使用组件的时候偶尔会遇见一些问题,比如说组件里只有某些东西自己并不需要,这个时候我们可以对组件进行简单的修改,而不影响其他 ...

  3. Goroutine(协程)为何能处理大并发?

    简单来说:协程十分轻量,可以在一个进程中执行有数以十万计的协程,依旧保持高性能. 进程.线程.协程的关系和区别: 进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度. 线程拥有自己独 ...

  4. java的super和this关键字用法总结

    ------super关键字------                 super用途:在子类中访问超类“被隐藏的成员变量(无论是否静态)和静态方法”以及“被重写的实例方法”.这里的超类必须是“直接 ...

  5. centos7.3使用squid搭建代理服务器

    centos7.3使用squid搭建代理服务器 1 安装 yum install squid 2 编辑 vi /etc/squid/squid.conf 3 设置 最底部增加 如下http_acces ...

  6. centos7.3nginx配置二级域名过程

    nginx1.10.2 1先检查 /etc/nginx/nginx.conf 是否include  conf.d include /etc/nginx/conf.d/*.conf; 默认都是包含的,如 ...

  7. js选择器 querySelector

    <form method="post" action="" id="myform"> <input type=" ...

  8. JAVA Spring JdbcTemplate ( 以 SQLSERVER 为例 ) 的简单使用

    < 1 > 配置文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=&q ...

  9. css之单边阴影

    css之单边阴影 需求:在网上找的其他博客上说单边阴影需要牺牲掉模糊,实际上牺牲掉模糊直接用border不就好了 效果: 原理: 1.在左边的外阴影就是右边的内阴影 2.将box-shadow写在be ...

  10. java ee7 配置文件

    java ee7 配置文件 1. 项目目录 # ee pom.xml      Maven构建文件 /src/main/java      Java源文件 /src/main/resource     ...