日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

每天一道LeetCode-----实现LFU置换算法

發布時間:2024/4/19 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 每天一道LeetCode-----实现LFU置换算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

LFU Cache

原題鏈接LFU Cache

實現LFU置換算法,置換規則是當容量滿時換出使用頻率最少的那個,不考慮一定時間內的頻率的情況下,可以采用每個頁使用的次數作為判斷依據,相當于從創建之初到現在的使用頻率

類似的置換算法為了在效率上有一定的保障,通常都是空間換時間,本題也明確規定的時間復雜度是O(1),而O(1)多數情況下都是類似map的存儲結構,當然,C++中map和set是采用紅黑樹實現的,效率是O(lgN),而另一個采用hashtable實現的unordered_map和unordered_set則是O(1)的效率

接下來考慮采用map保存的數據

首先為了根據鍵key找到值value和它的使用頻率freq,可以考慮保存一個類似unordered_map<int, std::pair<int, int>>的結構代表鍵到\<值,頻率>的映射。稱為keyToVF

接下來考慮當容量滿時進行置換的情況,為了讓效率進一步提升,可以借鑒類似操作系統內核處理不同狀態進程控制塊時的策略,即每種狀態的進程控制塊維護一個鏈表,這里就只需為每個頻率維護一個鏈表,再存儲在map中,即unordered_map<int, list<int>>結構代表頻率freq到保存鍵的鏈表的映射。稱為fToList

但是這樣仍然不夠,沒有辦法確定某一時刻最小的頻率是多少,所以還需要使用一個變量記錄當前最小使用頻率minF,當置換時,直接從fToList[minF]中移除一個頁,這里可以事先規定,新加入的都添加到鏈表尾部,移除則移除頭部

當調用get函數時需要對鍵key的頻率進行增加,從keyToVF中可以找到key對應的值和頻率,從fToList中可以找到頻率對應的鏈表,需要做的事情是從這個鏈表中刪除key,然后添加到fToList[freq+1]這個鏈表中。由于鏈表刪除與key相等的節點時需要遍歷鏈表,而刪除指定迭代器處的節點時只需要改變幾個指針,所以為了更進一步提高速度,再次使用一個map保存鍵key到key在鏈表中迭代器的映射即unordered_map<int, list<int>::iterator>。稱為keyToIt

至此三個map都已經構造完成,get和put的工作只是在線性時間操作不同的map而已

代碼如下

class LFUCache { public:LFUCache(int capacity) {capacity_ = capacity;size_ = 0;minF_ = 1;}int get(int key) {/* 不存在key */if(keyToVF_.find(key) == keyToVF_.end()) return -1;/* 將key從key的頻率map中刪除,然后加到freq+1的鏈表中 */fToList_[keyToVF_[key].second].erase(keyToIt_[key]);fToList_[++keyToVF_[key].second].push_back(key);keyToIt_[key] = --fToList_[keyToVF_[key].second].end();/* 更新最小頻率 */if(fToList_[minF_].empty())++minF_;return keyToVF_[key].first;}void put(int key, int value) {if(capacity_ == 0) return;/* 將頻率加一,返回非-1表示存在key,重新設置value即可 */if(get(key) != -1){keyToVF_[key].first = value;return;}if(size_ == capacity_){/* 刪除頻率最小的鏈表頭 */keyToVF_.erase(fToList_[minF_].front());keyToIt_.erase(fToList_[minF_].front());fToList_[minF_].pop_front();--size_;}/* 添加數據到頻率為1的鏈表中 */keyToVF_[key] = std::make_pair(value, 1);fToList_[1].push_back(key);keyToIt_[key] = --fToList_[1].end();minF_ = 1;++size_;} private:unordered_map<int, std::pair<int, int>> keyToVF_;unordered_map<int, list<int>::iterator> keyToIt_;unordered_map<int, list<int>> fToList_;int capacity_;int size_;int minF_; };/*** Your LFUCache object will be instantiated and called as such:* LFUCache obj = new LFUCache(capacity);* int param_1 = obj.get(key);* obj.put(key,value);*/

今天才發現csdn的markdown的<>是敏感字符….

總結

以上是生活随笔為你收集整理的每天一道LeetCode-----实现LFU置换算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。