恩...安卓实训终于做完了 这边继续开更
很多简单的题目慢慢来更把,首先解决接受率比较低的
这次做的是LRUCache
原题如下
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.
首先想到的是这样的思路
- 使用单链表来存
- 主类里存的是头结点 尾结点
- 每次get遍历从head结点开始,直到找到或者到头为止
- 每次put如果是已经有的key,修改其值,并放到链表尾
- 如果是没有的值则新建一个结点放到尾巴上
- 如果容量满了则去删改头结点
代码如下
package lru.cache;
public class LRUCache2 {
private Item head,tail;
private Integer capacity;
private Integer count;
public LRUCache2(int capacity) {
this.capacity = capacity;
count= 0;
head = null;
tail = null;
}
public int get(int key) {
if(head == null)
return -1;
if(head.key == key)
return head.value;
if(tail.key == key)
return tail.value;
Item theValue = head.next;
Item theValueBefore = head;
while(theValue != null){
if(theValue.key == key ){
theValueBefore.next = theValue.next;
tail.next = theValue;
tail = theValue;
theValue.next = null;
return theValue.value;
}
theValueBefore = theValue;
theValue = theValue.next;
}
return -1;
}
public void set(int key, int value) {
if(head == null){
head = new Item(value, key, null);
tail = head;
}
Item temp = checkKeyPresent(key);
if(temp != null){
temp.value = value;
}else{
if(capacity.equals(count)){
head = head.next;
tail.next = new Item(value, key, null);
tail = tail.next;
}else{
tail.next = new Item(value, key, null);
tail = tail.next;
count ++ ;
}
}
}
public Item checkKeyPresent(int key){
Item temp = head ;
while(temp != null){
if(temp.key == key )
return temp;
temp = temp.next;
}
return null;
}
class Item{
public int value;
public int key;
public Item next;
public Item(int value, int key, Item next) {
super();
this.value = value;
this.key = key;
this.next = next;
}
}
}
这样的做的结果是
这个方法在capacity=2048时 timeout了
超时了啊...
好吧,从新审视一下
最耗时间的部分是set时需要
遍!历!已!经!有!的!全!部!结!点!
那么如果没有这个过程,或者这个过程消耗时间极短,效率应该会大幅上升再想KYY VALUE 好吧
hashMap就决定是你了!
而为了维护最近最少使用这一点, 还是维护链表最为方便,如果使用数组很难记录最近使用这个数值
对上述代码进行修改!
所以Key将作为索引,本质还是一个双向链表
talk is cheap,show you the code
更多的问题看注释就好
package lru.cache;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
/*
* 之前用链表写的效率太差
* 仔细检查代码
* 发现最耗时间的部分是set时
* 遍!历!已!经!有!的!全!部!结!点!
* 那么如果没有这个过程,或者这个过程消耗时间极短
* 就可以了...再想KYY VALUE 好吧
* hashMap就决定是你了!
* 而为了维护最近最少使用这一点
* 还是维护链表最为方便,如果使用数组很难记录最近使用这个数值
* 所以对上述代码进行修改!
* 所以Key将作为索引,本质还是一个链表
*/
public class LRUCache {
private HashMap cache;
private Item head, tail;
private int capacity;
private int count;
public LRUCache(int capacity) {
cache = new HashMap(capacity);
this.capacity = capacity;
count= 0;
head = null;
tail = null;
}
public int get(int key) {
if(cache.isEmpty())
return -1;
if(!cache.keySet().contains(key))
return -1;
Item temp = cache.get(key);
//分4种情况,分别为既是头结点又是尾结点、只是头结点、
//只是尾结点和既不是头结点又不是尾结点
if(temp.previous == null && temp.next ==null){
return temp.value;
}else if(temp.previous == null){
head = temp.next;
head.previous = null;
tail.next = temp;
temp.previous = tail;
tail = temp;
temp.next = null;
return temp.value;
}else if(temp.next == null){
return temp.value;
}else{
temp.previous.next = temp.next;
temp.next.previous = temp.previous;
temp.previous = tail;
tail.next = temp;
temp.next = null;
tail = temp;
return temp.value;
}
}
public void set(int key, int value) {
if(cache.isEmpty()){
head = new Item(key,value);
tail = head;
cache.put(key, head);
count ++;
return;
}
Item temp = cache.get(key);
if(temp != null){
//如果存在,则修改该值,并且放到尾结点
temp.value = value;
if(head == tail){
//如果是头结点又是尾结点
//null
}else if(temp.previous == null && temp.next != null){
//如果只是头节点
head = temp.next;
head.previous = null;
tail.next = temp;
temp.previous = tail;
tail = temp;
}else if(temp.next == null && temp.previous != null){
//如果只是尾结点
//null
}else {
temp.next.previous = temp.previous;
temp.previous.next = temp.next;
tail.next = temp;
temp.previous = tail;
temp.next = null;
tail = temp;
}
}else{
//如果不存在
if(capacity > count ){
//不存在,且内容没满,则新建一个结点,放到尾部
temp = new Item(key,value);
tail.next = temp;
temp.previous = tail;
tail = temp;
count ++ ;
cache.put(key, temp);
}else{
//不存在且内容已满,则修改头结点中内容,并放到尾巴上
if(head == tail){
temp = head;
cache.remove(temp.key);
temp.value = value;
temp.key = key;
cache.put(key, head);
}else{
temp = head;
cache.remove(temp.key);
temp.value = value;
temp.key = key;
head = head.next;
head.previous = null;
temp.next = null;
tail.next = temp;
temp.previous = tail;
tail = temp;
cache.put(key, temp);
}
}
}
}
class Item{
public int value;
public int key;
public Item previous;
public Item next;
public Item(int key,int value) {
super();
this.value = value;
this.key = key;
this.next = null;
this.previous = null;
}
}
}