您的位置:首页 > 其它

leetcode----LRU Cache

2014-12-23 20:14 246 查看
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的简单的解释   下午就在leetcode上面看到了这道题目   编了半天的代码  忽然发现题意理解错了 原来在调用get方法的时候 需要把对应用到的数据放到最前面  表示最新使用了(前提是get测的值已经在队列里面了)  吃完晚饭回来  继续写代码  终于用单向链表实现了这个算法  可是提交以后忽然发现   时间复杂度超过了。。。真悲剧~~~先贴一张单链表的实现:

public class LRUCache {
private LRUclass first ;
private int cap;//整个cache中的对象上限
private int num = 0;//整个cache中有了多少个对象

private class LRUclass{
int key;
int value;
LRUclass next;
LRUclass(int k,int v){
this.key = k;
this.value = v;
}
}

public LRUCache(int capacity) {
cap = capacity;
}

public int get(int key) {
int result = -1;//用来存放结果的 控件值。
if(first==null) return -1;
LRUclass test = first;
LRUclass befortest = first;//用来记录 test 前面的那个值
for(int i=0;i<num;i++){
if(test.key == key) {
result = test.value; break;}
else {befortest = test;test = test.next;}//这样只要上面检测到含有相关的key值 befortest 就是test 前一个值
}

if(result != -1){ //当result不等于-1这就说明 链表里面有相关的值
befortest.next = test.next;//将test值间隔开
LRUclass oldfirst = first;//将test放到链表的最前面
first = test;
first.next = oldfirst;
}
return result;
}

public void set(int key, int value) {
if(num==0){first = new LRUclass(key,value);num++;return;}
if(==-1){
LRUclass oldfirst = first;
first = new LRUclass(key,value);
first.next = oldfirst;
num++;
if(num>cap){
num = cap;
}
}
else {
get(key);
first.key = key;
first.value = value;
}
}
}
后来又好好地想了一下  很明显是我的算法数据结构选择有问题,单向链表不能够实现最小的时间复杂度,原因是调用get方法的时候来检查链表里面有没有相关的数据的时候  总是需要for循环  另外  在调用set方法的时候又要调用一次get方法  上网查了一下大神们的做法  一般都是用双向链表+hashMap实现的  hashTable用来验证链表里面是不是有要查找的元素,如果有直接就可以拿到此元素的前一个元素和后一个元素形成新的链表  此外 很容易就可以将含有的元素调到表头。
贴一下   网上的一般性做法
<pre name="code" class="java"><pre class="prettyprint cs" style="padding: 0.3em; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: rgb(51, 51, 51); border-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; font-size: 13px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); overflow-y: auto; background-color: rgb(246, 246, 246);"><span class="keyword" style="font-weight: bold;">public</span> <span class="keyword" style="font-weight: bold;">class</span> LRUCache {
HashMap<Integer, Node> map;
Node head, tail;
<span class="keyword" style="font-weight: bold;">int</span> size;
<span class="comment" style="color: rgb(153, 153, 136); font-style: italic;">//使用双向链表和map,map将k对应与链表的节点</span>
<span class="comment" style="color: rgb(153, 153, 136); font-style: italic;">//链表里保存k和value</span>
<span class="keyword" style="font-weight: bold;">public</span> LRUCache(<span class="keyword" style="font-weight: bold;">int</span> capacity) {
map = <span class="keyword" style="font-weight: bold;">new</span> HashMap<Integer, Node>(capacity);
size = capacity;
head = <span class="keyword" style="font-weight: bold;">new</span> Node(-<span class="number" style="color: rgb(0, 153, 153);">1</span>, -<span class="number" style="color: rgb(0, 153, 153);">1</span>);
tail = <span class="keyword" style="font-weight: bold;">new</span> Node(<span class="number" style="color: rgb(0, 153, 153);">1</span>, <span class="number" style="color: rgb(0, 153, 153);">1</span>);
head.next = tail;
tail.pre = head;
}

<span class="keyword" style="font-weight: bold;">public</span> <span class="keyword" style="font-weight: bold;">int</span> <span class="keyword" style="font-weight: bold;">get</span>(<span class="keyword" style="font-weight: bold;">int</span> key) {
<span class="indent">  </span><span class="comment" style="color: rgb(153, 153, 136); font-style: italic;">//如果map里面有key,那么链表里面也有k</span>
<span class="indent">  </span><span class="comment" style="color: rgb(153, 153, 136); font-style: italic;">//取出节点的val,并把节点放到队首</span>
<span class="keyword" style="font-weight: bold;">if</span> (map.containsKey(key)) {
Node p = map.<span class="keyword" style="font-weight: bold;">get</span>(key);
putToHead(p);
<span class="keyword" style="font-weight: bold;">return</span> p.val;
}
<span class="keyword" style="font-weight: bold;">else</span>
<span class="keyword" style="font-weight: bold;">return</span> -<span class="number" style="color: rgb(0, 153, 153);">1</span>;
}

<span class="indent">  </span><span class="keyword" style="font-weight: bold;">public</span> <span class="keyword" style="font-weight: bold;">void</span> <span class="keyword" style="font-weight: bold;">set</span>(<span class="keyword" style="font-weight: bold;">int</span> key, <span class="keyword" style="font-weight: bold;">int</span> <span class="keyword" style="font-weight: bold;">value</span>) {
<span class="indent">  </span>    <span class="comment" style="color: rgb(153, 153, 136); font-style: italic;">//如果map里面有,只更新val</span>
<span class="indent">  </span><span class="keyword" style="font-weight: bold;">if</span> (map.containsKey(key)) {
<span class="indent">  </span><span class="indent">  </span>Node p = map.<span class="keyword" style="font-weight: bold;">get</span>(key);
<span class="indent">  </span><span class="indent">  </span>p.val = <span class="keyword" style="font-weight: bold;">value</span>;
<span class="indent">  </span><span class="indent">  </span>putToHead(p);
<span class="indent">  </span>}
<span class="indent">  </span><span class="comment" style="color: rgb(153, 153, 136); font-style: italic;">//如果map里没有而且没有超过capacity</span>
<span class="indent">  </span><span class="comment" style="color: rgb(153, 153, 136); font-style: italic;">//链表和map里面插入新的节点。</span>
<span class="indent">  </span><span class="keyword" style="font-weight: bold;">else</span> <span class="keyword" style="font-weight: bold;">if</span> (map.size() < size){
<span class="indent">  </span><span class="indent">  </span>Node p = <span class="keyword" style="font-weight: bold;">new</span> Node(key, <span class="keyword" style="font-weight: bold;">value</span>);
<span class="indent">  </span><span class="indent">  </span>putToHead(p);
<span class="indent">  </span><span class="indent">  </span>map.put(key, p);
<span class="indent">  </span>}
<span class="indent">  </span><span class="comment" style="color: rgb(153, 153, 136); font-style: italic;">//如果map里没有,且达到capacity</span>
<span class="indent">  </span>&l
aaa3
t;span class="comment" style="color: rgb(153, 153, 136); font-style: italic;">//移除队尾,将新节点插到队首,并且移除map里面的k</span>
<span class="indent">  </span><span class="keyword" style="font-weight: bold;">else</span> {
<span class="indent">  </span><span class="indent">  </span>Node p = <span class="keyword" style="font-weight: bold;">new</span> Node(key, <span class="keyword" style="font-weight: bold;">value</span>);
<span class="indent">  </span><span class="indent">  </span>putToHead(p);
<span class="indent">  </span><span class="indent">  </span>map.put(key, p);
<span class="indent">  </span><span class="indent">  </span><span class="keyword" style="font-weight: bold;">int</span> tmpk = removeEnd();
<span class="indent">  </span><span class="indent">  </span>map.remove(tmpk);
<span class="indent">  </span>}
}
<span class="indent">  </span>
<span class="indent">  </span><span class="keyword" style="font-weight: bold;">private</span> <span class="keyword" style="font-weight: bold;">int</span> removeEnd() {
<span class="indent">  </span><span class="indent">  </span>Node p = tail.pre;
<span class="indent">  </span><span class="indent">  </span>tail.pre.pre.next = tail;
<span class="indent">  </span><span class="indent">  </span>tail.pre = p.pre;
<span class="indent">  </span><span class="indent">  </span>p.pre = <span class="keyword" style="font-weight: bold;">null</span>;
<span class="indent">  </span><span class="indent">  </span>p.next = <span class="keyword" style="font-weight: bold;">null</span>;
<span class="indent">  </span><span class="indent">  </span><span class="keyword" style="font-weight: bold;">return</span> p.k;
<span class="indent">  </span>}

<span class="indent">  </span><span class="keyword" style="font-weight: bold;">private</span> <span class="keyword" style="font-weight: bold;">void</span> putToHead(Node p) {
<span class="indent">  </span><span class="indent">  </span><span class="keyword" style="font-weight: bold;">if</span>(p.next != <span class="keyword" style="font-weight: bold;">null</span> && p.pre != <span class="keyword" style="font-weight: bold;">null</span>) {
<span class="indent">  </span><span class="indent">  </span><span class="indent">  </span>p.pre.next = p.next;
<span class="indent">  </span><span class="indent">  </span><span class="indent">  </span>p.next.pre = p.pre;
<span class="indent">  </span><span class="indent">  </span>}
<span class="indent">  </span><span class="indent">  </span>p.pre = head;
<span class="indent">  </span><span class="indent">  </span>p.next = head.next;
<span class="indent">  </span><span class="indent">  </span>head.next.pre = p;
<span class="indent">  </span><span class="indent">  </span>head.next = p;
<span class="indent">  </span>}

}

<span class="keyword" style="font-weight: bold;">class</span> Node {
<span class="indent">  </span>Node pre;
<span class="indent">  </span>Node next;
<span class="indent">  </span><span class="keyword" style="font-weight: bold;">int</span> k;
<span class="indent">  </span><span class="keyword" style="font-weight: bold;">int</span> val;
<span class="indent">  </span>Node(<span class="keyword" style="font-weight: bold;">int</span> k, <span class="keyword" style="font-weight: bold;">int</span> val) {
<span class="indent">  </span><span class="indent">  </span><span class="keyword" style="font-weight: bold;">this</span>.k = k;
<span class="indent">  </span><span class="indent">  </span><span class="keyword" style="font-weight: bold;">this</span>.val = val;
<span class="indent">  </span>}
}
实现算法的时候多想想有没有几种数据结构组合的形式缩短时间复杂度 真是醉了 多动动脑子


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: