Last updated
Last updated
LRU Cache 這是一題經典題型,完全沒有概念的讀者我會建議一開始直接先看解答,懂概念後再做也沒關係的題目,因為這道題目的原理並不難,不如先把所有的東西都先搞定,面試前做熟就好了,因為就算知道原理,在真正要寫出 Code 的時候太多細節需要要求了,而且就算面試中面試官跟你講解了 LRU 快取的概念,沒有看過做法,真的很難做出來。
LRU Cache 個這裡一開始我就打算直接破題,這個題目的敘述可以直接到 LeetCode 上面看。
如果這輩子從來沒有寫過 LRU Cache 尤其大學不是念資工系的學生(像是我),極少數人應該可以在 45 分鐘內想到這題目需要用到 Doubly Linked List + Hash Table 。就算是上課有提到,我想教授應該也會直接跟大家講這個題目的核心觀念,不用太折騰自己要在 45 分鐘想出並寫完。
Doubly Linked List 可以幫我們做兩件事情,在 的時間複雜度的情況下,在新增、刪除、查看後的情況下,不斷地幫我們保持最後一次使用到的資料在這筆資料的最尾端。
那為什麼需要雙向?因為我們在新增、刪除節點的時候,我們才能知道該節點的前一個節點的資訊,確保操作可以在時間複雜度 。
Linked List 並不像陣列一樣可以靠位置來快速定位到我們想要的元素,所以我們需要 Hash Map ,當我們用某個 key 值來搜尋時,快速定位到 Linked List 上節點的位置。這個概念在 的系列問題裡面有用到。
這題目其實是難在懂了原理後要怎麼樣把細節都做出來。前面有說此題目需要 Doubly Linked List ,但是 LeetCode 上面的答案其實省略了這一個部分,我覺得其實把 Doubly Linked List 獨立寫出來並不會多花太多時間,但是會比 LeetCode 上面的答案更容易理解。
他的資料結構並不難,我們需要兩個指針 head
和 tail
來形成一個雙向指標結構的區間,並且記錄我們目前的資料長度為多少(size)。
而這個題目的特性,我們只要完成三個功能就好
當新增、查詢的時候,都要將該筆資料移動到最後的 add_to_last
。
移除節點 remove_node
。
透過移除節點移除第一個節點 remode_first_node
,這是當資料的數量超過限制的空間時,需要的操作
不知道你同不同意,我前面有說到完全沒有聽過 LRU Cache 的話,很難想得到它的實作細節,但是其實在 Python 裡面有一個內建的方法很簡單,他可以快速的幫你做出 Doubly Linked List + Hash Map 的功能,那就是 OrderedDict()
這是一個有序的 dict
。
而如果熟悉他的 API 的話,OrderDict 內建一個函式叫做 move_to_end
於是可以改寫成: