LeetCode之路2,LRUCache 最近最少使用算法

恩...安卓實訓(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;
        }

    }

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 我委在柔軟的沙發(fā)里,想著歲月贈我的點滴,節(jié)日依黃昏,孤單癡冥想,未來可期否?欲奔向遠(yuǎn)方踏尋,千山萬水蝶飛舞,草木青...
    amanda_green閱讀 154評論 0 0
  • 是的!從今天開始,全中國一年一次的全民大遷徙——春運就要開始了! 不論你是剛考完試的學(xué)生族小單身狗,還是打完述職報...
    臭不要臉妖閱讀 10,029評論 0 14
  • 題目 來源: 優(yōu)達(dá)學(xué)城--編程基礎(chǔ):python內(nèi)容:使用 turtle 畫出你想象。效果演示: 我的解法 步驟 ...
    codinghjy閱讀 823評論 0 0
  • 中國是世界上最早發(fā)行和流通紙幣的國家,宋元明清四朝都曾經(jīng)印行過紙幣。而作為官方發(fā)行的唯一紙幣,明朝只有“大明寶鈔”...
    一夕厘閱讀 2,229評論 0 0
  • 從來沒有一個時代,像現(xiàn)在一樣迅捷、開放、海量信息隨手拈來。我們從公眾號上獲取各種好玩有趣、新鮮奇怪、干貨有料的信息...
    幸福的眼淚閱讀 1,068評論 1 3