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. Hibernate 一对多/多对多

    一对多关联(多对一): 一对多关联映射: 在多的一端添加一个外键指向一的一端,它维护的关系是一指向多 多对一关联映射: 咋多的一端加入一个外键指向一的一端,它维护的关系是多指向一 在配置文件中添加: ...

  2. html基础代码示例

    文档结构 <!-- 声明文档的类型 标记该文档为HTML5的文件 --> <!DOCTYPE html> <!-- 页面的根节点 --> <!-- html中 ...

  3. Spark 编程模型(上)

    Spark的编程模型 核心概念(注意对比MR里的概念来学习) Spark Application的组成 Spark Application基本概念 Spark Application编程模型 回顾sc ...

  4. 抽象工厂模式( Abstract Factory )

    提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类.解决多产品多等级结构.模式的类图如下: 抽象工厂模式的优点: 易于交换产品系列,由于具体工厂类在一个应用中只需要在初始化的时候出现一 ...

  5. Executor框架(六)CompletionService 接口

      CompletionService 接口是一个独立的接口,并没有扩展 ExecutorService . 其默认实现类是ExecutorCompletionService;   接口 Comple ...

  6. C++官方文档-this

    #include <iostream> using namespace std; class Dummy { public: int x; Dummy() : x() { } ; Dumm ...

  7. jap 事务总结

    参考: JPA事务总结 2010年4月13日 - 从表11-2中可以看出,对于不同的EntityManager类型与所运行的环境,所支持的事务类型是不一样的. 其中两种情况下最为简单,一种是容器托管的 ...

  8. HTML5 Canvas ( 文字横纵对齐 ) textAlign, textBaseLine

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  9. leetcode447

    public class Solution { /// <summary> /// 计算两个点的距离 /// </summary> /// <param name=&qu ...

  10. shiro 注解式前提

    <aop:config proxy-target-class="true"></aop:config> <bean class="org.a ...