Leetcode - LRU Cache

Screenshot from 2016-01-24 20:55:47.png

My code:

public class LRUCache {
    private class Node {
        Node next;
        Node prev;
        int key;
        int val;
        private Node(int key, int val) {
            this.key = key;
            this.val = val;
        }
    }
    
    private final int capacity;
    private int counter;
    private HashMap<Integer, Node> LRU;
    private Node head;
    private Node tail;
    
    public LRUCache(int capacity) {
        this.capacity = capacity;
        counter = 0;
        LRU = new HashMap<Integer, Node>();
    }
    
    public int get(int key) {
        if (LRU.containsKey(key)) {
            Node temp = LRU.get(key);
            int ret = temp.val;
            remove(temp);
            addToFirst(temp);
            return ret;
        }
        else 
            return -1;
    }
    
    public void set(int key, int value) {
        if (LRU.containsKey(key)) {
            Node temp = LRU.get(key);
            temp.val = value;
            remove(temp);
            addToFirst(temp);
        }
        else {
            counter++;
            Node temp = new Node(key, value);
            addToFirst(temp);
            LRU.put(key, temp);
            if (counter > capacity) {
                LRU.remove(tail.key);
                remove(tail);
                counter = capacity;
            }
        }
    }
    
    private void remove(Node temp) {
        if (temp == null)
            return;
        if (temp.prev == null) { // head node
            if (temp.next == null) {
                head = null;
                tail = null;
            }
            else {
                head = temp.next;
                temp.next.prev = null;
            }
        }
        else if (temp.next == null) { // tail nod
            if (temp.prev == null) {
                head = null;
                tail = null;
            }
            else {
                tail = temp.prev;
                temp.prev.next = null;
            }
        }
        else {
            temp.prev.next = temp.next;
            temp.next.prev = temp.prev;
        }
    }
    
    private void addToFirst(Node p) {
        if (p == null)
            return;
        if (head == null) {
            head = p;
            tail = p;
        }
        else {
            head.prev = p;
            p.next = head;
            p.prev = null;
            head = p;
        }
    }
}

這道題目還是挺有意思的。一開(kāi)始寫(xiě)出來(lái)超出時(shí)間了市咆,沒(méi)有怎么仔細(xì)分析秤掌。
兩個(gè)操作愁铺,
get,
set,最理想情況下都必須 O(1)
因?yàn)楫?dāng)超過(guò)限度后,需要把最不常用的刪除掉闻鉴,所以茵乱,為了使時(shí)間復(fù)雜度最低,必須得用鏈表孟岛。
然后瓶竭,get操作督勺,根據(jù)key返回value,復(fù)雜度要O(1)斤贰,所以要用HashMap
那么key value 各自是什么呢智哀?
key -> Integer, value -> Node(int key, int value)

Screenshot from 2016-01-24 21:00:13.png

然后我們get操作時(shí),通過(guò)HashMap的key來(lái)找到Node再返回他的value荧恍。
然后再根據(jù)這個(gè)Node瓷叫,將其從當(dāng)前位置刪除,移動(dòng)到首結(jié)點(diǎn)位置送巡。
我們?cè)谶M(jìn)行set操作時(shí)摹菠,如果HashMap已經(jīng)存在了這個(gè)key,那么直接修改原值骗爆,然后移動(dòng)到鏈表頭部次氨。
如果沒(méi)有,則新建結(jié)點(diǎn)摘投,插到頭部煮寡。如果超過(guò)了限度,那么就把尾巴刪除掉谷朝。記得先從哈希表中刪除該鍵值對(duì)洲押,再刪除該結(jié)點(diǎn)(尾結(jié)點(diǎn))武花。所以圆凰,Node里面必須要有key這個(gè)成員。然后再通過(guò)key去哈希表里面刪除對(duì)應(yīng)的鍵值對(duì)体箕。
這道題目就是得思考专钉,get, set操作需要那幾個(gè)原子級(jí)別的操作。
然后發(fā)現(xiàn)需要HashMap, 和鏈表累铅。然后需要有添加頭結(jié)點(diǎn)跃须,刪除特定結(jié)點(diǎn)的操作。
參考網(wǎng)頁(yè):
http://www.programcreek.com/2013/03/leetcode-lru-cache-java/

Anyway, Good luck, Richardo!

My code:

public class LRUCache {
    private class ListNode {
        ListNode pre;
        ListNode next;
        int key;
        int val;
        ListNode(int key, int val) {
            this.key = key;
            this.val = val;
        }
    }
    
    HashMap<Integer, ListNode> map = new HashMap<Integer, ListNode>();
    int capacity = 0;
    ListNode dummy = new ListNode(-1, -1);
    ListNode tail = dummy;
    int size = 0;
    public LRUCache(int capacity) {
        this.capacity = capacity;
    }
    
    public int get(int key) {
        if (!map.containsKey(key)) {
            return -1;
        }
        ListNode node = map.get(key);
        remove(node);
        addFirst(node);
        return node.val;
    }
    
    public void set(int key, int value) {
        if (map.containsKey(key)) {
            ListNode node = map.get(key);
            node.val = value;
            remove(node);
            // insert it at the head of list
            addFirst(node);
        }
        else {
            ListNode node = new ListNode(key, value);
            map.put(key, node);
            addFirst(node);
            size++;
            if (size > capacity) {
                map.remove(tail.key);
                remove(tail);
                size--;
            }
        }
    }
    
    private void addFirst(ListNode node) {
        ListNode head = dummy.next;
        dummy.next = node;
        node.pre = dummy;
        node.next = head;
        if (head != null) {
            head.pre = node;
        }
        else {
            tail = node;
        }
    }
    
    private void remove(ListNode node) {
        if (node.next == null) {
            tail = node.pre;
            node.pre.next = node.next;
        }
        else {
            node.pre.next = node.next;
            node.next.pre = node.pre;
        }
    }
}

這道題目寫(xiě)了挺久娃兽,挺慚愧的菇民。昨天還和人說(shuō)這是簡(jiǎn)單題。投储。第练。

主要就是,我想到了用雙向鏈表玛荞,但覺(jué)得沒(méi)必要那么認(rèn)真娇掏。
后來(lái)越改錯(cuò)誤越多。

于是勋眯,看了下答案婴梧。再重寫(xiě)了下下梢。

剛剛學(xué)長(zhǎng)和我說(shuō),Google今年三月份面過(guò)了塞蹭,被凍了一年孽江,不能再面了。番电。竟坛。
這是再開(kāi)玩笑嘛?钧舌?

Google, 就要這樣錯(cuò)過(guò)嗎担汤?
是不是很滑稽啊洼冻?崭歧??

Anyway, Good luck, Richardo! -- 09/15/2016

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末撞牢,一起剝皮案震驚了整個(gè)濱河市率碾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌屋彪,老刑警劉巖所宰,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異畜挥,居然都是意外死亡仔粥,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門蟹但,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)躯泰,“玉大人,你說(shuō)我怎么就攤上這事华糖÷笙颍” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵客叉,是天一觀的道長(zhǎng)诵竭。 經(jīng)常有香客問(wèn)我,道長(zhǎng)兼搏,這世上最難降的妖魔是什么卵慰? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮向族,結(jié)果婚禮上呵燕,老公的妹妹穿的比我還像新娘。我一直安慰自己件相,他們只是感情好再扭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布氧苍。 她就那樣靜靜地躺著,像睡著了一般泛范。 火紅的嫁衣襯著肌膚如雪让虐。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天罢荡,我揣著相機(jī)與錄音赡突,去河邊找鬼。 笑死区赵,一個(gè)胖子當(dāng)著我的面吹牛惭缰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播笼才,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼漱受,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了骡送?” 一聲冷哼從身側(cè)響起昂羡,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎摔踱,沒(méi)想到半個(gè)月后虐先,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡派敷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年蛹批,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片膀息。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡般眉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出潜支,到底是詐尸還是另有隱情,我是刑警寧澤柿汛,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布冗酿,位于F島的核電站,受9級(jí)特大地震影響络断,放射性物質(zhì)發(fā)生泄漏裁替。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一貌笨、第九天 我趴在偏房一處隱蔽的房頂上張望弱判。 院中可真熱鬧,春花似錦锥惋、人聲如沸昌腰。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)遭商。三九已至固灵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間劫流,已是汗流浹背巫玻。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留祠汇,地道東北人仍秤。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像可很,于是被迫代替她去往敵國(guó)和親徒扶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

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