题目

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.
get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(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.

LRU Cache

    LRU是Least Recent Used的缩写,即最少使用的Cache置换算法。是为虚拟页式存储管理服务的。Cache是快速缓存。这是IT行业常常见到的概念。CPU中的Cache能极大提高存取指令和数据的时间,让整个存储器(Cache+内存)既有Cache的快速度,又有内存的大容量。
    Cache尽管速度快,可是容量有限。因此当Cache容量用完而又有新的内容加入进来的时候,就须要选取Cache中的部分内容进行舍弃,然后加入新的内容。LRU Cache的替换规则是:每次选取最久不被使用的内容进行舍弃,然后加入新的内容。之前上操作系统,老师告诉我的LRU Cache Algorithm中文翻译是近期最久未使用算法。

思路

    LRU的典型实现是double linked list + hash map。

原理是:

  1. 双向链表根据每一个节点近期被訪问的时间有序存储,近期被訪问的节点存储在表头,近期没有被訪问的节点存储的表尾,存储根据是由于:近期被訪问的节点在接下来的一段时间仍有非常大的概率被再次訪问到。

  2. 哈希表的作用是用来提高查找效率,假设不使用哈希表。则查找一个节点的时间复杂度是O(n)。而使用了哈希表,则每一个节点的查找时间复杂度为O(1)。
    查找(GET)操作:
  • 依据键值查找hashmap,假设没找到直接返回-1
  • 若找到相应节点node,则将其插入到双向链表表头
  • 返回node的value值
    插入(SET)操作:
  • 依据键值查找hashmap。假设找到。则直接将该节点移到表头就可以
  • 假设没有找到。首先推断当前Cache是否已满
  • 假设已满,则删除表尾节点
  • 将新节点插入到表头

AC代码

    AC代码例如以下,写的比較乱,事实上非常多方法是能够简洁复用的,可是这里之所以不改,是为了让大家更好的清楚LRU的流程和原理:
import java.util.HashMap;

public class LRUCache {
private HashMap<Integer, DoubleListNode> mHashMap;
private DoubleListNode head;
private DoubleListNode tail;
private int capacity;
private int currentsize; public LRUCache(int capacity) {
this.capacity = capacity;
this.currentsize = 0;
this.mHashMap = new HashMap<Integer, DoubleListNode>();
this.head = this.tail = null;
} public int get(int key) {
if (mHashMap.containsKey(key)) {
DoubleListNode tNode = mHashMap.get(key);
if (tNode == tail) {
if (currentsize > 1) {
removeNodeFromTail();
moveNodeToHead(tNode);
}
} else if (tNode == head) {
// do nothing
} else {
tNode.pre.next = tNode.next;
tNode.next.pre = tNode.pre;
moveNodeToHead(tNode);
}
return mHashMap.get(key).value;
} else {
return -1;
}
} private void removeNodeFromTail() {
tail = tail.pre;
if (tail != null) {
tail.next = null;
}
} private void moveNodeToHead(DoubleListNode node) {
head.pre = node;
node.next = head;
node.pre = null;
head = node;
} public void set(int key, int value) {
if (mHashMap.containsKey(key)) {
// 更新HashMap中相应的值,并将key相应的Node移至队头
DoubleListNode tNode = mHashMap.get(key);
tNode.value = value;
if (tNode == tail) {
if (currentsize > 1) {
removeNodeFromTail();
moveNodeToHead(tNode);
}
} else if (tNode == head) {
// do nothing
} else {
tNode.pre.next = tNode.next;
tNode.next.pre = tNode.pre;
moveNodeToHead(tNode);
} mHashMap.put(key, tNode);
} else {
DoubleListNode node = new DoubleListNode(key, value);
mHashMap.put(key, node);
if (currentsize == 0) {
head = tail = node;
currentsize += 1;
} else if (currentsize < capacity) {
moveNodeToHead(node);
currentsize += 1;
} else {
// 删除tail节点。而且添加一个head节点
mHashMap.remove(tail.key);
removeNodeFromTail(); // 添加头节点
moveNodeToHead(node);
}
}
} public static void main(String[] args) {
LRUCache lruCache = new LRUCache(1);
lruCache.set(2, 1);
System.out.println(lruCache.get(2));
lruCache.set(3, 2);
System.out.println(lruCache.get(2));
System.out.println(lruCache.get(3));
} private static class DoubleListNode {
public DoubleListNode pre;
public DoubleListNode next;
public int key;
public int value; public DoubleListNode(int key, int value) {
this.key = key;
this.value = value;
this.pre = this.next = null;
}
} }

LRU算法&amp;&amp;LeetCode解题报告的更多相关文章

  1. leetcode解题报告(2):Remove Duplicates from Sorted ArrayII

    描述 Follow up for "Remove Duplicates": What if duplicates are allowed at most twice? For ex ...

  2. 2021字节跳动校招秋招算法面试真题解题报告--leetcode206 反转链表,内含7种语言答案

    206.反转链表 1.题目描述 反转一个单链表. 示例: 输入: 1->2->3->4->5->NULL输出: 5->4->3->2->1-> ...

  3. LeetCode解题报告:Linked List Cycle && Linked List Cycle II

    LeetCode解题报告:Linked List Cycle && Linked List Cycle II 1题目 Linked List Cycle Given a linked ...

  4. 2021字节跳动校招秋招算法面试真题解题报告--leetcode19 删除链表的倒数第 n 个结点,内含7种语言答案

    2021字节跳动校招秋招算法面试真题解题报告--leetcode19 删除链表的倒数第 n 个结点,内含7种语言答案 1.题目描述 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点. ...

  5. LeetCode 解题报告索引

    最近在准备找工作的算法题,刷刷LeetCode,以下是我的解题报告索引,每一题几乎都有详细的说明,供各位码农参考.根据我自己做的进度持续更新中......                        ...

  6. LeetCode解题报告:LRU Cache

    LRU Cache Design and implement a data structure for Least Recently Used (LRU) cache. It should suppo ...

  7. LeetCode解题报告—— Search in Rotated Sorted Array & Search for a Range & Valid Sudoku

    1. Search in Rotated Sorted Array Suppose an array sorted in ascending order is rotated(轮流,循环) at so ...

  8. LeetCode解题报告—— 1-bit and 2-bit Characters & 132 Pattern & 3Sum

    1. 1-bit and 2-bit Characters We have two special characters. The first character can be represented ...

  9. leetCode解题报告5道题(六)

    题目一: Longest Substring Without Repeating Characters Given a string, find the length of the longest s ...

随机推荐

  1. ipad在非viewport 1:1下缩放问题

    1.最小会有980宽度,小于980应设置viewport 2.fix元素使用100%指定宽度时,默认会以min-width或980作为尺寸,可以选择给定与页面缩放时触发定宽来设置宽度,或设置设置bod ...

  2. uvalive 6185

    高斯消元,以前从来没写过,今天的模拟比赛里面,添琦给了我一个模板! 虽然是个裸的,但是因为从来没写过,一个小细节竟然搞了我几个小时: 终于最后在小珺同志的帮助下成功a掉了,太开心了! 存一下,作为模板 ...

  3. Json 返回日期格式转换

    //日期转换 function ChangeDateFormat(time) { if (time != null) { var date = new Date(parseInt(time.repla ...

  4. ruby迭代器iterator和枚举器Enumerator

    编写自定义的迭代器 The defining feature of an iterator method is that it invokes a block of code associatedwi ...

  5. 矩阵, 矩阵 , Android基础控件之ImageView

    天下文章大家抄,以下所有内容,有来自copy,有来自查询,亦有自己的总结(目的是总结出自己的东西),所以说原创,不合适,说是转载也不恰当,所以我称之为笔记,可惜没有此分类选项,姑且不要脸一点,选择为原 ...

  6. Android之获得内存剩余大小与总大小

    方法一: 如何查看android对应用的内存限制 每款手机对应用的限制都是不一样的,毕竟硬件不同,我们可以使用如下方式来查看单独的应用可使用的最大内存: 执行命令: adb shell getprop ...

  7. BZOJ_1497_[NOI2006]_最大获利_(最大流+最大权闭合图)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1497 共n个站点,给出建立每个站点所需要的花费.现在有m个客户需要开通服务,每个客户需要有两个 ...

  8. 20个可以帮你简化iOS app开发流程的工具

    这里推荐20个可以帮你简化iOS app开发流程的工具.很多开发者都使用过这些工具,涉及原型和设计.编程.测试以及最后的营销,基本上涵盖了整个开发过程. 原型和设计 有了一个很好的创意后,你要做的不是 ...

  9. Unity3D之多个fbx导入场景, 合并多个动画

    1:先导入到合适的文件夹, Unity自动刷新, 生成相应的文件. 2:在Project视图中选中单个fbx, 在Inspector中选择"Rig", 更改"Animat ...

  10. AppScan修复漏洞:启用不安全的HTTP方法

    最近对于系统使用Appscan扫描出中危漏洞“启用不安全的HTTP方法,找了很多修复方法都不能达到效果. 漏洞截图: 漏洞描述: 危险级别   中危险 影响页面   整个WEB页面. 简短描述   管 ...