LeetCode #146 LRU Cache LRU緩存機(jī)制

146 LRU Cache LRU緩存機(jī)制

Description:
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(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.

The cache is initialized with a positive capacity.

Follow up:
Could you do both operations in O(1) time complexity?

Example:

LRUCache cache = new LRUCache( 2 /* capacity */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // returns 1
cache.put(3, 3);    // evicts key 2
cache.get(2);       // returns -1 (not found)
cache.put(4, 4);    // evicts key 1
cache.get(1);       // returns -1 (not found)
cache.get(3);       // returns 3
cache.get(4);       // returns 4

題目描述:
運(yùn)用你所掌握的數(shù)據(jù)結(jié)構(gòu)写烤,設(shè)計(jì)和實(shí)現(xiàn)一個 LRU (最近最少使用) 緩存機(jī)制迅腔。它應(yīng)該支持以下操作: 獲取數(shù)據(jù) get 和 寫入數(shù)據(jù) put 挚瘟。

獲取數(shù)據(jù) get(key) - 如果關(guān)鍵字 (key) 存在于緩存中恶守,則獲取關(guān)鍵字的值(總是正數(shù)),否則返回 -1戳鹅。
寫入數(shù)據(jù) put(key, value) - 如果關(guān)鍵字已經(jīng)存在,則變更其數(shù)據(jù)值;如果關(guān)鍵字不存在磺芭,則插入該組「關(guān)鍵字/值」。當(dāng)緩存容量達(dá)到上限時醉箕,它應(yīng)該在寫入新數(shù)據(jù)之前刪除最久未使用的數(shù)據(jù)值钾腺,從而為新的數(shù)據(jù)值留出空間。

進(jìn)階:

你是否可以在 O(1) 時間復(fù)雜度內(nèi)完成這兩種操作讥裤?

示例 :

LRUCache cache = new LRUCache( 2 /* 緩存容量 */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // 返回  1
cache.put(3, 3);    // 該操作會使得關(guān)鍵字 2 作廢
cache.get(2);       // 返回 -1 (未找到)
cache.put(4, 4);    // 該操作會使得關(guān)鍵字 1 作廢
cache.get(1);       // 返回 -1 (未找到)
cache.get(3);       // 返回  3
cache.get(4);       // 返回  4

思路:

采用雙鏈表和哈希表結(jié)合的方式
哈希表查找時間為 O(1)
get函數(shù)實(shí)現(xiàn)思路: key不存在直接返回 -1; 否則將 key對應(yīng)的 value移動到雙鏈表開頭
put函數(shù)實(shí)現(xiàn)思路: key已經(jīng)存在, 將舊節(jié)點(diǎn)刪除, 放入新節(jié)點(diǎn); 若 cache已經(jīng)滿了, 刪除雙鏈表結(jié)尾, 刪除 map中對應(yīng)的 key, 將新節(jié)點(diǎn)插入到 cache, 對應(yīng)的 key插入到 map
時間復(fù)雜度O(1), 空間復(fù)雜度O(n)

代碼:
C++:

class LRUCache 
{
private:
    list<pair<int, int>> l;
    unordered_map<int, list<pair<int, int>>::iterator> m;
    int cap;
public:
    LRUCache (int capacity) 
    {
        cap = capacity;
    }
    
    int get(int key) 
    {
        if (m.find(key) != m.end())
        {
            int result = (*m[key]).second;
            l.erase(m[key]);
            l.push_front(make_pair(key, result));
            m[key] = l.begin();
            return result;
        }
        return -1;
    }
    
    void put(int key, int value) 
    {
        if (m.find(key) != m.end())
        {
            l.erase(m[key]);
            l.push_front(make_pair(key, value));
            m[key] = l.begin();
        }
        else
        {
            if (l.size() == cap)
            {
                m.erase(l.back().first);
                l.pop_back();
            }
            l.push_front(make_pair(key, value));
            m[key] = l.begin();
        }
    }
};

/**
 * 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);
 */

Java:

class LRUCache extends LinkedHashMap<Integer, Integer>{
    private int capacity;
    
    public LRUCache(int capacity) {
        super(capacity, 0.75F, true);
        this.capacity = capacity;
    }

    public int get(int key) {
        return super.getOrDefault(key, -1);
    }

    public void put(int key, int value) {
        super.put(key, value);
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
        return size() > capacity; 
    }
}

/**
 * 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);
 */

Python:

class LRUCache(dict):
    def __init__(self, capacity: int):
        self.c = capacity

    def get(self, key: int) -> int:
        if key in self:
            self[key] = self.pop(key)
            return self[key]    
        return -1    

    def put(self, key: int, value: int) -> None:
        key in self and self.pop(key) 
        self[key] = value
        len(self) > self.c and self.pop(next(iter(self)))

# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末放棒,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子己英,更是在濱河造成了極大的恐慌间螟,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件损肛,死亡現(xiàn)場離奇詭異厢破,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)治拿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門摩泪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人劫谅,你說我怎么就攤上這事见坑。” “怎么了捏检?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵荞驴,是天一觀的道長。 經(jīng)常有香客問我贯城,道長戴尸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任冤狡,我火速辦了婚禮孙蒙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘悲雳。我一直安慰自己挎峦,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布合瓢。 她就那樣靜靜地躺著坦胶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上顿苇,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天峭咒,我揣著相機(jī)與錄音,去河邊找鬼纪岁。 笑死凑队,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的幔翰。 我是一名探鬼主播漩氨,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼遗增!你這毒婦竟也來了叫惊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤做修,失蹤者是張志新(化名)和其女友劉穎霍狰,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體饰及,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蚓耽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了旋炒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡签杈,死狀恐怖瘫镇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情答姥,我是刑警寧澤铣除,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站鹦付,受9級特大地震影響尚粘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜敲长,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一郎嫁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧祈噪,春花似錦泽铛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春弛随,著一層夾襖步出監(jiān)牢的瞬間瓢喉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工舀透, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留栓票,地道東北人。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓盐杂,卻偏偏與公主長得像逗载,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子链烈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評論 2 355