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. How can I detect multiple logins into a Django web application from different locations?

    1) Install django-tracking (thankyou for that tip Van Gale Google Maps + GeoIP is amazing!) 2) Add t ...

  2. ios 动画 创建一个UIImageView并将其属性设置animationImages为UIImages 的数组

    NSArray *animationFrames = [NSArray arrayWithObjects: [UIImage imageWithName:@"image1.png" ...

  3. python爬虫学习研究

    目标:做一个小爬虫项目 2017年6月4日13:32:17       mooc网教程Python爬虫入门一之综述要学习Python爬虫,我们要学习的共有以下几点:Python基础知识Python中u ...

  4. C语言合并两个集合(L,L1) 将L1中不在L中的元素插入到L线性表中

    void main(){ Sqlist L,L1; InitList(&L); InitList(&L1); ListInsert(&L, 1, 2); ListInsert( ...

  5. 几种动态调用js函数方案的性能比较

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. ural 1303 Minimal Coverage【贪心】

    链接: http://acm.timus.ru/problem.aspx?space=1&num=1303 http://acm.hust.edu.cn/vjudge/contest/view ...

  7. MyEclipse2014新增bug,尝鲜的朋友需注意NotFoundException: org.springframework.web.context.ContextLoaderListener

    事实上标题后面加上这个异常信息并不合适,可是为了方便和我遇到相同问题的童鞋搜到这篇文章.我不得不这样写啦. 这个异常和你的程序没有关系,假设你没有忘记增加spring Jar包的话,这是fucking ...

  8. python2 生成验证码图片

    使用pillow或者pil库编写 #coding:utf-8 #use pillow or pil try: from PIL import Image, ImageDraw, ImageFont, ...

  9. 中国移动OnetNet云平台 GET指令使用

    GET /devices//datastreams/KEY HTTP/1.1 Host: api.heclouds.com api-key: pmWLtnkDBSreKfvg7GsClUXdXa4A ...

  10. Kindeditor 函数用途

    1.loadScript  加载文件   2.updateState 更新工具条状态   afterCreate在dom加载的时候执行,dom加载完之前执行的 K.ready dom加载完之后执行   ...