leetcode146-LRU緩存機(jī)制

LRU緩存機(jī)制

運(yùn)用你所掌握的數(shù)據(jù)結(jié)構(gòu)霎箍,設(shè)計(jì)和實(shí)現(xiàn)一個(gè) LRU (最近最少使用) 緩存機(jī)制 贫奠。
實(shí)現(xiàn) LRUCache 類:

LRUCache(int capacity) 以正整數(shù)作為容量 capacity 初始化 LRU 緩存
int get(int key) 如果關(guān)鍵字 key 存在于緩存中舱权,則返回關(guān)鍵字的值逾冬,否則返回 -1 包吝。
void put(int key, int value) 如果關(guān)鍵字已經(jīng)存在锥余,則變更其數(shù)據(jù)值腹纳;如果關(guān)鍵字不存在,則插入該組「關(guān)鍵字-值」驱犹。當(dāng)緩存容量達(dá)到上限時(shí)嘲恍,它應(yīng)該在寫入新數(shù)據(jù)之前刪除最久未使用的數(shù)據(jù)值,從而為新的數(shù)據(jù)值留出空間雄驹。

進(jìn)階:你是否可以在 O(1) 時(shí)間復(fù)雜度內(nèi)完成這兩種操作佃牛?

示例:

輸入
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
輸出
[null, null, null, 1, null, -1, null, -1, 3, 4]

解釋
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 緩存是 {1=1}
lRUCache.put(2, 2); // 緩存是 {1=1, 2=2}
lRUCache.get(1);    // 返回 1
lRUCache.put(3, 3); // 該操作會使得關(guān)鍵字 2 作廢,緩存是 {1=1, 3=3}
lRUCache.get(2);    // 返回 -1 (未找到)
lRUCache.put(4, 4); // 該操作會使得關(guān)鍵字 1 作廢医舆,緩存是 {4=4, 3=3}
lRUCache.get(1);    // 返回 -1 (未找到)
lRUCache.get(3);    // 返回 3
lRUCache.get(4);    // 返回 4

思路:

一個(gè)hash俘侠,一個(gè)鏈表

代碼:

import java.util.HashMap;
public class LRUCache {
    //當(dāng)前節(jié)點(diǎn)個(gè)數(shù)
    private int curNum=0;
    //最大節(jié)點(diǎn)個(gè)數(shù)
    private int maxNum;
    //一個(gè)鏈表
    private LRUNode head=null;
    //一個(gè)指向鏈表尾部節(jié)點(diǎn)的指針
    private LRUNode tail=null;
    private HashMap<Integer,LRUNode> map =new HashMap<>();
    public LRUCache(int capacity) {
        this.maxNum=capacity;
    }

    public int get(int key) {
        if(map.containsKey(key)){
            //如果當(dāng)前大小為1或者查詢的是頭節(jié)點(diǎn),那么直接返回
            if(map.get(key)==head||curNum==1){
                return map.get(key).value;
            }
            LRUNode temp=map.get(key);
            LRUNode prevNode=temp.prev;
            LRUNode nextNode=temp.next;
            //如果當(dāng)前查詢的節(jié)點(diǎn)是尾節(jié)點(diǎn)蔬将,那么需要更改尾節(jié)點(diǎn)爷速,否則不需要修改
            if(temp==tail){
                tail=temp.prev;
                tail.next=null;
                temp.next=head;
                head.prev=temp;
                head=temp;
                return temp.value;
            }
            else{
                prevNode.next=nextNode;
                nextNode.prev=prevNode;
                if(prevNode.prev==null){
                    prevNode.prev=temp;
                }
                temp.next=head;
                //更改頭節(jié)點(diǎn)
                head.prev=temp;
                head=temp;
                return temp.value;
            }
        }
        else{return -1;}
    }

    public void put(int key, int value) {
        //查詢的節(jié)點(diǎn)已存在
        if(this.get(key)!=-1){
            //此時(shí)查詢的節(jié)點(diǎn)已經(jīng)是頭節(jié)點(diǎn)
            head.value=value;
        }
        //新節(jié)點(diǎn)
        else{
            LRUNode node =new LRUNode(null,null,key,value);
            map.put(key,node);
            if(curNum==0){
                head=node;
                tail=node;
                curNum++;
            }
            else if(curNum==1&&maxNum==1){
                map.remove(tail.key);
                head=node;
                tail=node;
            }
            //當(dāng)前不為空
            else{
                //判斷是否達(dá)到緩存是否已滿
                if(curNum==maxNum){
                    map.remove(tail.key);
                    tail=tail.prev;
                    tail.next=null;
                    head.prev=node;
                    node.next=head;
                    head=node;
                }
                else{node.next=head;
                    head.prev=node;
                    head=node;
                    curNum++;
                }
            }
        }
    }
    class LRUNode{
        LRUNode prev;
        LRUNode next;
        int key;
        int value;
        LRUNode(LRUNode prev,LRUNode next,int key,int value){
            this.prev=prev;
            this.next=next;
            this.key=key;
            this.value=value;
        }
    }
}

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市霞怀,隨后出現(xiàn)的幾起案子惫东,更是在濱河造成了極大的恐慌,老刑警劉巖里烦,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凿蒜,死亡現(xiàn)場離奇詭異,居然都是意外死亡胁黑,警方通過查閱死者的電腦和手機(jī)废封,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丧蘸,“玉大人漂洋,你說我怎么就攤上這事遥皂。” “怎么了刽漂?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵演训,是天一觀的道長。 經(jīng)常有香客問我贝咙,道長样悟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任庭猩,我火速辦了婚禮窟她,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蔼水。我一直安慰自己震糖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布趴腋。 她就那樣靜靜地躺著吊说,像睡著了一般。 火紅的嫁衣襯著肌膚如雪优炬。 梳的紋絲不亂的頭發(fā)上颁井,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天,我揣著相機(jī)與錄音穿剖,去河邊找鬼蚤蔓。 笑死,一個(gè)胖子當(dāng)著我的面吹牛糊余,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播单寂,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼贬芥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了宣决?” 一聲冷哼從身側(cè)響起蘸劈,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎尊沸,沒想到半個(gè)月后威沫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡洼专,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年棒掠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屁商。...
    茶點(diǎn)故事閱讀 40,001評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡烟很,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情雾袱,我是刑警寧澤恤筛,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站芹橡,受9級特大地震影響毒坛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜林说,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一煎殷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧述么,春花似錦蝌数、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至剑梳,卻和暖如春唆貌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背垢乙。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工锨咙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人追逮。 一個(gè)月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓酪刀,卻偏偏與公主長得像,于是被迫代替她去往敵國和親钮孵。 傳聞我的和親對象是個(gè)殘疾皇子骂倘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評論 2 355