恩...安卓實訓(xùn)終于做完了 這邊繼續(xù)開更
很多簡單的題目慢慢來更把,首先解決接受率比較低的
這次做的是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.
首先想到的是這樣的思路
- 使用單鏈表來存
- 主類里存的是頭結(jié)點 尾結(jié)點
- 每次get遍歷從head結(jié)點開始,直到找到或者到頭為止
- 每次put如果是已經(jīng)有的key,修改其值,并放到鏈表尾
- 如果是沒有的值則新建一個結(jié)點放到尾巴上
- 如果容量滿了則去刪改頭結(jié)點
代碼如下
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;
}
}
}
這樣的做的結(jié)果是
這個方法在capacity=2048時 timeout了
超時了啊...
好吧,從新審視一下
最耗時間的部分是set時需要
遍!歷!已!經(jīng)!有!的!全!部!結(jié)!點!
那么如果沒有這個過程,或者這個過程消耗時間極短,效率應(yīng)該會大幅上升再想KYY VALUE 好吧
hashMap就決定是你了!
而為了維護(hù)最近最少使用這一點, 還是維護(hù)鏈表最為方便,如果使用數(shù)組很難記錄最近使用這個數(shù)值
對上述代碼進(jìn)行修改!
所以Key將作為索引,本質(zhì)還是一個雙向鏈表
talk is cheap,show you the code
更多的問題看注釋就好
package lru.cache;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
/*
* 之前用鏈表寫的效率太差
* 仔細(xì)檢查代碼
* 發(fā)現(xiàn)最耗時間的部分是set時
* 遍!歷!已!經(jīng)!有!的!全!部!結(jié)!點!
* 那么如果沒有這個過程,或者這個過程消耗時間極短
* 就可以了...再想KYY VALUE 好吧
* hashMap就決定是你了!
* 而為了維護(hù)最近最少使用這一點
* 還是維護(hù)鏈表最為方便,如果使用數(shù)組很難記錄最近使用這個數(shù)值
* 所以對上述代碼進(jìn)行修改!
* 所以Key將作為索引,本質(zhì)還是一個鏈表
*/
public class LRUCache {
private HashMap<Integer, Item> cache;
private Item head, tail;
private int capacity;
private int count;
public LRUCache(int capacity) {
cache = new HashMap<Integer, LRUCache.Item>(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種情況,分別為既是頭結(jié)點又是尾結(jié)點、只是頭結(jié)點、
//只是尾結(jié)點和既不是頭結(jié)點又不是尾結(jié)點
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){
//如果存在,則修改該值,并且放到尾結(jié)點
temp.value = value;
if(head == tail){
//如果是頭結(jié)點又是尾結(jié)點
//null
}else if(temp.previous == null && temp.next != null){
//如果只是頭節(jié)點
head = temp.next;
head.previous = null;
tail.next = temp;
temp.previous = tail;
tail = temp;
}else if(temp.next == null && temp.previous != null){
//如果只是尾結(jié)點
//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 ){
//不存在,且內(nèi)容沒滿,則新建一個結(jié)點,放到尾部
temp = new Item(key,value);
tail.next = temp;
temp.previous = tail;
tail = temp;
count ++ ;
cache.put(key, temp);
}else{
//不存在且內(nèi)容已滿,則修改頭結(jié)點中內(nèi)容,并放到尾巴上
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;
}
}
}