【設計】B001_用隊列實現棧(雙端隊列 + Map / Map + 自定義雙向鏈表 (代辦))

一、Problem

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?


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

二、Solution

方法一:暴力做法

直接用 Map + LinkedList 做:

  • put 時,檢查 key 是否有對應的 v
    • 如果有,則覆蓋掉 Map 中的值,並且 q 的大小不能查過 cap,如果超了,pollFirst
    • 否則,map 添加鍵值對
  • get 時,也是先判空,此時的 key 爲使用過,所以要變新。

刪除操作耗費時間…

class LRUCache {
    Map<Integer, Integer> mp;
    ArrayDeque<Integer> q;
    int cap;
    public LRUCache(int capacity) {
        mp = new HashMap<>(capacity);
        q = new ArrayDeque<>();
        cap = capacity;
    }
    
    public int get(int key) {
        Integer v = mp.get(key);
        if (v != null) {
            q.remove(key);
            q.add(key);
            return v;
        }
        return -1;
    }
    
    public void put(int key, int value) {
        Integer v = mp.get(key);
        if (v != null) {
            q.remove(key);
            q.add(key);
        } else if (q.size() < cap){
            q.add(key);
        } else {
            int oldKey = q.pollFirst();
            q.add(key);
            mp.remove(oldKey);
        }
        mp.put(key, value);
    }
}

複雜度分析

  • 時間複雜度:O(...)O(...)
  • 空間複雜度:O(...)O(...)

方法二:雙向鏈表 + Map

  • 定義一個 Node 內部類,存儲 k、v、pre、next
  • map 就存儲 <K, Node> 類型的鍵值對,這樣就可以通過 k 用 O(1)O(1) 的時間找到 v,然後通過修改指針的指向來刪除結點和添加結點。

複雜度分析

  • 時間複雜度:O(1)O(1)
  • 空間複雜度:O(cap)O(cap)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章