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,这里自定义越靠近链表头的node,在越近的时间使用过。支持两个操作——get和set:

  1. get(key):如果链表中有key对应的node,返回该node的值,并把node移到链表头部(最近使用过);如果没有,返回-1;
  2. set(key,value):如果链表中已经有key对应的node,修改对应node的值为value(但不需要把这个node放在头结点处);如果链表中没有key对应的node,那么要新建node插入链表中,但此时要看链表是否还有空间。如果没有,就将尾部node(最少使用的node)删除,然后在头部插入新的node。

为了提高查找效率,这里使用一个hashMap存放<key,node>键值对,这样就可以在O(1)的时间判断cache中是否存在对应的key。

代码如下:

 public class LRUCache {
private class Node{
int value;
int key;
Node before;
Node after;
public Node(int key,int value){
this.value = value;
this.key = key;
before = null;
after = null;
}
} private int capacity;
private HashMap<Integer, Node> map = new HashMap<Integer,Node>();
private Node headNode = new Node(-1, -1);
private Node tailNode = new Node(-1, -1); public LRUCache(int capacity) {
this.capacity = capacity;
headNode.after = tailNode;
tailNode.before = headNode;
} public void move_to_head(Node current){
current.after = headNode.after;
headNode.after = current;
current.before = headNode;
current.after.before = current;
}
public int get(int key) {
//if we don't have this node
if(!map.containsKey(key))
return -1; //if we have this node, get it and move it to head
Node current = map.get(key);
current.before.after = current.after;
current.after.before = current.before;
move_to_head(current); return map.get(key).value;
} public void set(int key, int value) {
//if we already have this node,just change its value
if(get(key) != -1){
map.get(key).value = value;
return;
} //if we indeed don't have this node, we first check capacity
if(map.size() == capacity){
map.remove(tailNode.before.key);
tailNode.before.before.after = tailNode;
tailNode.before = tailNode.before.before;
} //now we are sure we have space for this new node,put it ahead of the list
Node newNode = new Node(key, value);
map.put(key, newNode);
move_to_head(newNode);
}
}

在实现的时候,还设置了两个node:head和tail,真正的cache数据节点存放在二者之间。

【leetcode刷题笔记】LRU Cache的更多相关文章

  1. LeetCode刷题笔记和想法(C++)

    主要用于记录在LeetCode刷题的过程中学习到的一些思想和自己的想法,希望通过leetcode提升自己的编程素养 :p 高效leetcode刷题小诀窍(这只是目前对我自己而言的小方法,之后会根据自己 ...

  2. 18.9.10 LeetCode刷题笔记

    本人算法还是比较菜的,因此大部分在刷基础题,高手勿喷 选择Python进行刷题,因为坑少,所以不太想用CPP: 1.买股票的最佳时期2 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. ...

  3. LeetCode刷题笔记 - 12. 整数转罗马数字

    学好算法很重要,然后要学好算法,大量的练习是必不可少的,LeetCode是我经常去的一个刷题网站,上面的题目非常详细,各个标签的题目都有,可以整体练习,本公众号后续会带大家做一做上面的算法题. 官方链 ...

  4. Leetcode刷题笔记(双指针)

    1.何为双指针 双指针主要用来遍历数组,两个指针指向不同的元素,从而协同完成任务.我们也可以类比这个概念,推广到多个数组的多个指针. 若两个指针指向同一数组,遍历方向相同且不会相交,可以称之为滑动窗口 ...

  5. LeetCode刷题笔记(1-9)

    LeetCode1-9 本文更多是作为一个习题笔记,没有太多讲解 1.两数之和 题目请点击链接 ↑ 最先想到暴力解法,直接双循环,但是这样复杂度为n平方 public int[] twoSum(int ...

  6. leetcode刷题笔记

    (1)Best Time to Buy and Sell Stock Total Accepted: 10430 Total Submissions: 33800My Submissions Say ...

  7. leetcode刷题笔记08 字符串转整数 (atoi)

    题目描述 实现 atoi,将字符串转为整数. 在找到第一个非空字符之前,需要移除掉字符串中的空格字符.如果第一个非空字符是正号或负号,选取该符号,并将其与后面尽可能多的连续的数字组合起来,这部分字符即 ...

  8. LeetCode刷题笔记-回溯法-分割回文串

    题目描述: 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回 s 所有可能的分割方案. 示例: 输入: "aab"输出:[ ["aa", ...

  9. leetcode刷题笔记231 2的幂

    题目描述: 给定一个整数,写一个函数来判断它是否是2的幂. 题目分析: 判断一个整数是不是2的幂,可根据二进制来分析.2的幂如2,4,8,等有一个特点: 二进制数首位为1,其他位为0,如2为10,4为 ...

随机推荐

  1. jQuery动态加载JS以减少服务器压力

    如果您要创建一个web2.0的应用程序,那么你的网页会包括大量的JavaScript文件,这些可能会拖慢您的网页.因此,动态加载JavaScript代码到您的网页是一个好主意,即只有当实用他们的时候加 ...

  2. Tomcat startup.bat启动隐藏弹出的信息窗口

    to make tomcat to use javaw.exe instead of java.exe using some startup parameter or environment vari ...

  3. PHP-Manual的学习----【序言】

    2017年6月27日16:57:32 学习资料:2015-PHP-Manual 打好坚实的基础是做任何事的前提 序言: 笔记: 1.PHP,即"PHP: Hypertext Preproce ...

  4. Solr In Action 中文版 第一章(四、五)

    1.1             功能概览1. 4 最后,让我们再依照以下的分类.高速的过一下Solr的主要功能: ·用户体验 ·数据建模 ·Solr 4的新功能 在本书中.为你的用户提供良好的搜索体验 ...

  5. socket java 实例

    简单的java socket 示例 一.搭建服务器端 a).创建ServerSocket对象绑定监听端口. b).通过accept()方法监听客户端的请求. c).建立连接后,通过输入输出流读取客户端 ...

  6. Django 视图之CBV

    CBV 所谓的CBV(class base view) 在视图里面,用类的方式来写逻辑 那么对于FBV,CBV有什么优势? CBV(class base views) 就是在视图里使用类处理请求. P ...

  7. Tensorflow 初级教程(一)

    初步介绍 Google 于2011年推出人工深度学习系统——DistBelief.通过DistBelief,Google能够扫描数据中心数以千计的核心,并建立更大的神经网络.Google 的这个系统将 ...

  8. SAP 改表方法

    SAP中直接修改表.视图的Tcode有SE16N和SM30. 1. SE16N修改表需要先输入命令&SAP_EDIT,回车左下角显示激活SAP编辑功能后,就可以对相应的表进行新增.删除.修改的 ...

  9. iOS block 闭包的学习

    iOS  闭包 学习 理解: 1 .   闭包外界无法访问内部变量 ,它是一个独立的代码块. 2 .   闭包可以作为 一个方法 ,甚至局部变量  全局 变量 3 .   闭包 是一种引用类型   注 ...

  10. Python 3 mysql 数据类型

    Python 3 mysql 数据类型 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选的 详细参考: http://www.runoob.com/m ...