設計複雜度爲O(1)的LRU緩存結構

題目描述

設計LRU緩存結構,該結構在構造時確定大小,假設大小爲K,並有如下兩個功能

  • set(key, value):將記錄(key, value)插入該結構
  • get(key):返回key對應的value值
[要求]
  • set和get方法的時間複雜度爲O(1)
  • 某個key的set或get操作一旦發生,認爲這個key的記錄成了最常使用的。
  • 當緩存的大小超過K時,移除最不經常使用的記錄,即set或get最久遠的。
    若opt=1,接下來兩個整數x, y,表示set(x, y)
    若opt=2,接下來一個整數x,表示get(x),若x未出現過或已被移除,則返回-1
    對於每個操作2,輸出一個答案
示例1
輸入
複製
[[1,1,1],[1,2,2],[1,3,2],[2,1],[1,4,4],[2,2]],3
輸出
複製
[1,-1]
說明
第一次操作後:最常使用的記錄爲("1", 1)
第二次操作後:最常使用的記錄爲("2", 2),("1", 1)變爲最不常用的
第三次操作後:最常使用的記錄爲("3", 2),("1", 1)還是最不常用的
第四次操作後:最常用的記錄爲("1", 1),("2", 2)變爲最不常用的
第五次操作後:大小超過了3,所以移除此時最不常使用的記錄("2", 2),加入記錄("4", 4),並且爲最常使用的記錄,然後("3", 2)變爲最不常使用的記錄
完整代碼
#include <unordered_map>
class Solution {
public:
    
    // 維護一個有序單向鏈表,當有一個新的數據被訪問時,從鏈表頭部開始遍歷鏈表:
    // 1 如果此數據之前已經在緩存中了,那麼將其從原來的位置刪除,並將其插入到頭節點
    // 2 如果此數據之前不在緩存中:
    //   2.1 如果緩存未滿,則直接將此節點插入到頭節點
    //   2.2 如果緩存已滿,則刪除鏈表尾節點,將新的數據插入到頭節點
    // 複雜度爲O(n)
     
     
    // 使用散列表hashtable與雙向鏈表的組合
    // 當要緩存某個數據的時候,先在鏈表中查找這個數據。如果沒有找到,則直接將數據放到鏈表的尾部;如果找到了,我們就把它移動到鏈表的尾部
    // 當緩存空間不夠,需要淘汰一個數據的時候,我們就直接將鏈表頭部的結點刪除
    // 複雜度爲O(1)
    
    unordered_map<int, int> map;
    vector<int> cache;
    
    vector<int> LRU(vector<vector<int> >& operators, int k) {
        // write code here
        vector<int> result;
        for(int i = 0; i < operators.size(); i++){
            if(operators[i][0] == 1){
                set(operators[i][1], operators[i][2], k);
            }else if(operators[i][0] == 2){
                result.push_back(get(operators[i][1]));
            }
        }
        return result;
        
    }
    
    void set(int key, int value, int k){
        if(cache.size()== k){
            map.erase(cache[0]);
            cache.erase(cache.begin());
        }
        map[key] = value;
        // 這個時候應該先查找cache中是否存在key,如果存在就把它刪除後放到尾部
        for(int i = 0; i < cache.size(); i++){
            if(cache[i] == key){
                // 刪除
                cache.erase(cache.begin() + i);
                break;
            }
        }
        // 放到尾部
        cache.push_back(key);
    }
    
    int get(int key){
        // 根本不存在或者已經被刪除了
        if(map.find(key) == map.end()){
            return -1;
        }
        // 這個時候應該先查找cache中是否存在key,如果存在就把它刪除後放到尾部
        for(int i = 0; i < cache.size(); i++){
            if(cache[i] == key){
                // 刪除
                cache.erase(cache.begin() + i);
                // 放到尾部
                cache.push_back(key);
                break;
            }
        }
        return map[key];
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章