LeetCode146 動(dòng)手實(shí)現(xiàn)LRU算法

146. LRU緩存機(jī)制

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

獲取數(shù)據(jù) get(key) - 如果密鑰 (key) 存在于緩存中,則獲取密鑰的值(總是正數(shù))健无,否則返回 -1。
寫入數(shù)據(jù) put(key, value) - 如果密鑰不存在液斜,則寫入其數(shù)據(jù)值累贤。當(dāng)緩存容量達(dá)到上限時(shí),它應(yīng)該在寫入新數(shù)據(jù)之前刪除最近最少使用的數(shù)據(jù)值少漆,從而為新的數(shù)據(jù)值留出空間臼膏。

進(jìn)階:

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

示例:

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

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // 返回  1
cache.put(3, 3);    // 該操作會(huì)使得密鑰 2 作廢
cache.get(2);       // 返回 -1 (未找到)
cache.put(4, 4);    // 該操作會(huì)使得密鑰 1 作廢
cache.get(1);       // 返回 -1 (未找到)
cache.get(3);       // 返回  3
cache.get(4);       // 返回  4

解題思路

  • LRU是Least Recently Used的縮寫,即"最近最少使用",也就是說,LRU緩存把最近最少使用的數(shù)據(jù)移除,讓給最新讀取的數(shù)據(jù)
  • 往往最常讀取的,也是讀取次數(shù)最多的
  • 操作系統(tǒng)等最常使用的緩存策略,即LRU
  • 需要在O(1)時(shí)間復(fù)雜度實(shí)現(xiàn)put操作,就需要使用雙向鏈表,方便移動(dòng)節(jié)點(diǎn)(單鏈表無法達(dá)到O(1))
  • O(1)實(shí)現(xiàn)get查詢操作,就需要使用map存key-node鍵值對(duì),實(shí)現(xiàn)快速查詢
  • 具體詳見代碼注釋

代碼實(shí)現(xiàn)

// doublyLinkedNode defines a node for double-linked-list
type doublyLinkedNode struct {
    prev, next *doublyLinkedNode
    key, val   int
}

// LRUCache defines a object for cache
type LRUCache struct {
    len, cap    int
    first, last *doublyLinkedNode         //head,tail
    nodes       map[int]*doublyLinkedNode //hashtable,find node in O(1)
}

// Constructor creates a cache object
func Constructor(capacity int) LRUCache {
    return LRUCache{
        len:   0,
        cap:   capacity,
        first: nil,
        last:  nil,
        nodes: make(map[int]*doublyLinkedNode, capacity),
    }
}

// Get returns value by key
func (l *LRUCache) Get(key int) int {
    if node, ok := l.nodes[key]; ok {
        //key exist
        // move the node to the head of double-linked-list
        l.moveToFirst(node)
        return node.val
    }

    //key not exist,return -1
    return -1
}

// Put puts key-value pair into LRUCache
func (l *LRUCache) Put(key int, value int) {
    if node, ok := l.nodes[key]; ok {
        //update value of old node
        node.val = value
        // move the node to the head of double-linked-list
        l.moveToFirst(node)
    } else {
        if l.len == l.cap {
            delete(l.nodes, l.last.key)
            l.removeLast()
        } else {
            l.len++
        }
        node := &doublyLinkedNode{
            prev: nil,
            next: nil,
            key:  key,
            val:  value,
        }
        l.nodes[key] = node
        l.insertToFirst(node)
    }
}

func (l *LRUCache) removeLast() {
    if l.last.prev != nil {
        //雙向鏈表長(zhǎng)度>1
        l.last.prev.next = nil
    } else {
        //雙向鏈表長(zhǎng)度 == 1,first == last
        l.first = nil
    }
    l.last = l.last.prev
}
func (l *LRUCache) moveToFirst(node *doublyLinkedNode) {
    switch node {
    case l.first:
        return
    case l.last:
        l.removeLast()
    default:
        //在雙向鏈中示损,刪除 node 節(jié)點(diǎn)
        node.prev.next = node.next
        node.next.prev = node.prev
    }
    // 策略是
    // 如果是移動(dòng)node
    // 先刪除,再插入
    l.insertToFirst(node)
}

func (l *LRUCache) insertToFirst(node *doublyLinkedNode) {
    if l.last == nil {
        //空的雙向鏈表
        l.last = node
    } else {
        node.next = l.first
        l.first.prev = node
    }
    l.first = node
}

GitHub

  • 源碼在這里
  • 項(xiàng)目中會(huì)提供各種數(shù)據(jù)結(jié)構(gòu)及算法的Golang實(shí)現(xiàn),以及 LeetCode 解法
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末渗磅,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子屎媳,更是在濱河造成了極大的恐慌夺溢,老刑警劉巖论巍,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烛谊,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡嘉汰,警方通過查閱死者的電腦和手機(jī)丹禀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鞋怀,“玉大人双泪,你說我怎么就攤上這事∶芩疲” “怎么了焙矛?”我有些...
    開封第一講書人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)残腌。 經(jīng)常有香客問我村斟,道長(zhǎng)贫导,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任蟆盹,我火速辦了婚禮孩灯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘逾滥。我一直安慰自己峰档,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開白布寨昙。 她就那樣靜靜地躺著讥巡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪毅待。 梳的紋絲不亂的頭發(fā)上尚卫,一...
    開封第一講書人閱讀 52,441評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音尸红,去河邊找鬼吱涉。 笑死,一個(gè)胖子當(dāng)著我的面吹牛外里,可吹牛的內(nèi)容都是我干的怎爵。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼盅蝗,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼鳖链!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起墩莫,我...
    開封第一講書人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤芙委,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后狂秦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灌侣,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年裂问,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了侧啼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡堪簿,死狀恐怖痊乾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情椭更,我是刑警寧澤哪审,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站虑瀑,受9級(jí)特大地震影響湿滓,放射性物質(zhì)發(fā)生泄漏畏腕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一茉稠、第九天 我趴在偏房一處隱蔽的房頂上張望描馅。 院中可真熱鬧,春花似錦而线、人聲如沸铭污。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嘹狞。三九已至,卻和暖如春誓竿,著一層夾襖步出監(jiān)牢的瞬間磅网,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來泰國打工筷屡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留涧偷,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓毙死,卻偏偏與公主長(zhǎng)得像燎潮,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子扼倘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

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

  • 關(guān)于Mongodb的全面總結(jié) MongoDB的內(nèi)部構(gòu)造《MongoDB The Definitive Guide》...
    中v中閱讀 31,947評(píng)論 2 89
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,111評(píng)論 1 32
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 29,417評(píng)論 8 265
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理确封,服務(wù)發(fā)現(xiàn),斷路器再菊,智...
    卡卡羅2017閱讀 134,704評(píng)論 18 139
  • 那些注定要相逢的 會(huì)在夢(mèng)里相逢 會(huì)在前生相逢 會(huì)在某次楞怔后 恍然若識(shí) 會(huì)在某個(gè)春天 踏過同一片綠葉 和衰敗擦肩 ...
    MrManMan閱讀 701評(píng)論 0 0