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.

思路:Java的LinkedHashMap可以实现最近最少使用(LRU)的次序。类似于HashMap。详见《JAVA编程思想(第4版)》P487.

题目要求是一个固定大小的cache,因此需要一个变量maxCapacity来记录容量大小,用LinkedHashMap存储数据。在添加数据set()方法时,判断一下是否达到maxCapacity,如果cache已经满了,remove掉最长时间不使用的数据,然后put进新的数据。

注意:HashMap,LinkedHashMap,TreeMap的区别,详细看看StackOverFlow

LinkedHashMap最常用的是LRU cache的实现。
如果用C++实现的话, hashmap + 双向链表:用 双向链表记录value 用hashmap记录 key值在链表中的位置(指针)。

unordered_map<int, list<CacheNode>:: iterator> cacheMap;

题解:

import java.util.LinkedHashMap;

public class LRUCache {

	LinkedHashMap<Integer, Integer> linkedmap;
int maxCapacity; public LRUCache(int capacity) {
this.maxCapacity = capacity;
this.linkedmap = new LinkedHashMap<Integer, Integer>(capacity, 1f, true);
} public int get(int key) {
if (linkedmap.containsKey(key))
return linkedmap.get(key);
else
return -1;
} public void set(int key, int value) {
int size = linkedmap.size();
if ((size < maxCapacity) || (linkedmap.containsKey(key))) {
linkedmap.put(key, value);
} else if (size >= maxCapacity) {
Iterator<Integer> it = linkedmap.keySet().iterator();//iterator method is superior the toArray(T[] a) method.
linkedmap.remove(it.next());
linkedmap.put(key, value);
}
}
}

结题遇到的问题:

1.下面这段代码提交的时候超时了。

import java.util.LinkedHashMap;

public class LRUCache {
LinkedHashMap<Integer, Integer> linkedmap;
int maxCapacity; public LRUCache(int capacity) {
this.maxCapacity = capacity;
this.linkedmap = new LinkedHashMap<Integer, Integer>(capacity, 1f, true);
} public int get(int key) {
if (linkedmap.containsKey(key))
return linkedmap.get(key);
else
return -1;
} public void set(int key, int value) {
int size = linkedmap.size();
if ((size < maxCapacity) || (linkedmap.containsKey(key))) {
linkedmap.put(key, value);
} else if (size >= maxCapacity) {
Integer[] keyArray = linkedmap.keySet().toArray(new Integer[0]);//这是超时的代码,采用Iterator不会超时。
linkedmap.remove(keyArray[0]);
linkedmap.put(key, value);
}
} }

2.Roger自己实现LinkedHashMap的功能,采用双向链表和哈希表。效率略低于LinkedHashMap.(644ms>548ms)  

import java.util.HashMap;

public class LRUCache {

	private HashMap<Integer, Entry<Integer>> index;
private UDFList<Integer> data; public LRUCache(int capacity) {
index = new HashMap<Integer, Entry<Integer>>(capacity);
data = new UDFList<Integer>(capacity);
} public int get(int key) {
if (!isExist(key)) {
index.remove(key);
return -1;
}
if (!index.get(key).equals(data.head)) {
Entry<Integer> nodePtr = data.adjust(index.get(key));
index.put(key, nodePtr);
}
return index.get(key).element;
} public void set(int key, int value) {
if (isExist(key)) {
data.remove(index.get(key));
}
index.put(key, data.push(value));
} private boolean isExist(int key) {
if (index.get(key) == null) {
return false;
}
if (index.get(key).element == null) {
return false;
}
return true;
} public class UDFList<E> {
public Entry<E> head;
public Entry<E> tail;
public final int size;
public int length = 0; public UDFList(int size) {
head = new Entry<E>(null, null, null);
tail = head;
this.size = size;
} public Entry<E> adjust(Entry<E> node) {
if (node.equals(tail)) {
tail = tail.previous;
tail.next = null;
node.previous = null;
} else if (node.equals(head)) {
node = null;
return head;
} else {
node.previous.next = node.next;
node.next.previous = node.previous;
}
head.previous = node;
node.next = head;
head = node;
node = null;
return head;
} public Entry<E> push(E e) {
Entry<E> newNode = new Entry<E>(e, null, null);
if (length == 0) {
head = newNode;
tail = head;
} else {
head.previous = newNode;
newNode.next = head;
head = newNode;
}
if (length == size) {
remove(tail);
}
length++;
return head;
} public void remove(Entry<E> node) {
if (node == null)
return;
node.element = null;
if (node.equals(head)) {
head = head.next;
} else if (node.equals(tail)) {
tail = tail.previous;
tail.next = null;
} else {
node.previous.next = node.next;
node.next.previous = node.previous;
}
node = null;
length--;
}
} public class Entry<E> {
public E element;
public Entry<E> previous;
public Entry<E> next; public Entry(E element, Entry<E> next, Entry<E> previous) {
this.element = element;
this.next = next;
this.previous = previous;
}
}
}

  

  

LeetCode解题报告:LRU Cache的更多相关文章

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

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

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

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

  3. LeetCode题解: LRU Cache 缓存设计

    LeetCode题解: LRU Cache 缓存设计 2014年12月10日 08:54:16 邴越 阅读数 1101更多 分类专栏: LeetCode   版权声明:本文为博主原创文章,遵循CC 4 ...

  4. 【LeetCode】146. LRU Cache 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 字典+双向链表 日期 题目地址:https://le ...

  5. LRU算法&amp;&amp;LeetCode解题报告

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

  6. LeetCode 解题报告索引

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

  7. 【LeetCode OJ】LRU Cache

    Problem Link: http://oj.leetcode.com/problems/lru-cache/ Long long ago, I had a post for implementin ...

  8. 【LeetCode】146. LRU Cache

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

  9. LeetCode OJ:LRU Cache(最近使用缓存)

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

随机推荐

  1. VC/MFC强制退出本进程自己,VC/MFC关闭自己

    正常情况下通过关闭主窗口close或发送PostQuitMessage(WM_QUIT);消息 能关闭窗口.但如果一个进程中包括多个子线程当子线程没有结束还占用 系统资源时通过上面的两种方法是不能立即 ...

  2. 使用CSS的类名交集复合选择器

    首先先看一下基本定义: 复合选择器就是两个或多个基本选择器,通过不同方式连接而成的选择器,主要包括“交集”选择器.“并集”选择器.“后代”选择器. 交集选择器 “交集”复合选择器是由两个选择器直接连接 ...

  3. Android canvas rotate():平移旋转坐标系至任意原点任意角度-------附:android反三角函数小结

    自然状态下,坐标系以屏幕左上角为原点,向右是x正轴,向下是y正轴.现在要使坐标系的原点平移至任一点O(x,y),且旋转a角度,如何实现? 交待下我的问题背景,已知屏幕上有两点p1和p2,构成直线l.我 ...

  4. HDU-1113(map的运用)

    Word Amalgamation Problem Description In millions of newspapers across the United States there is a ...

  5. JavaScript DOM编程艺术第二版学习(1/4)

    接下来项目需要网页相关知识,故在大牛的指引下前来阅读本书. 记录方式:本书分四部分阅读,完成阅读之后会多写一篇包括思维导图的算是阅读指南的东西,浏览的童鞋看着指南可以跳过一些不必要的坑~ 当前水平:H ...

  6. PAT_1008 数组元素循环右移问题

    题目描述: 一个数组A中存有N(N>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(M>=0)个位置,即将A中的数据由(A0A1……AN-1)变换为(AN-M …… AN ...

  7. Angularjs简介

    很久没有系统学习一个新技术了,angularjs将会比较系统的讲解这个技术的语法.应用.次类型的博客将会持续更新,博主也是一个初学者,如果有问题欢迎留言讨论. angularjs简介. angular ...

  8. 从外国html5网站上扒来一个鼠标经过的css3 效果,感觉很不错

    鼠标经过的时候,感觉有点像一张纸卷上去的感觉. 下面是代码 <div class="main-container types"> <div class=" ...

  9. pip 的 Assert Error

    在Ubuntu 14.04 中安装了Python之后,使用pip freeze,出现AssertError. 发现是pip版本太低,只有1.5.6 更新pip之后就OK了.

  10. Linux 信号量同步编程

    前一篇文章概述了Linux 系统中信号量互斥编程,这篇文章正好是前一篇的姊妹篇----信号量同步.说它们是姊妹篇是因为它们都是利用了内核的信号量机制实现了进程间的通信.因为两者所解决的问题不同,因此它 ...