LFU 緩存

題目鏈接

LFU 緩存

題目描述


注意點

  • 1 <= capacity <= 10^4
  • 0 <= key <= 10^5
  • 0 <= value <= 10^9
  • 對緩存中的鍵執行 get 或 put 操作,使用計數器的值將會遞增
  • 當緩存達到其容量 capacity 時,則應該在插入新項之前,移除最不經常使用的項
  • 函數 get 和 put 必須以 O(1) 的平均時間復雜度運行

解答思路

  • 創建Node雙向鏈表節點類,其中包含freq,key,value,prev指針,next指針
  • 兩個Map,kvMap存儲鍵值對,freqMap存儲頻率以及對應頻率的鏈表頭尾節點,capacity存儲容量,minFreq存儲最小調用頻率
  • 做get()操作時,如果key無相應節點,直接返回-1;如果有相應節點,則其頻率要加一,要從原頻率鏈表中移除該節點,并將該節點加入到新頻率的鏈表中,還要注意更新minFreq的值
  • 做put()操作時
    • 如果key有相應節點,則取出原有節點,將原有節點取出,將其頻率加一,從原頻率鏈表中移除該節點,并將該節點加入到新頻率的鏈表中,還要注意更新minFreq的值
    • 如果key無相應節點,則需要新建一個節點,寫入key,value,freq為1,再將該節點加入到kvMap和freqMap對應頻率鏈表中,還要判斷此時kvMap是否已滿,如果節點過多還要移除最不經常使用的節點,也就是最低頻率minFreq對應鏈表中的第一個節點,還要注意更新minFreq的值為1

代碼

class LFUCache {// 最小調用頻率int minFreq;// 容量int capacity;// key->key,value->對應節點Map<Integer, Node> kvMap;// key->使用頻率,value->對應鏈表的頭尾節點Map<Integer, Node[]> freqMap;public LFUCache(int capacity) {minFreq = 0;this.capacity = capacity;kvMap = new HashMap<>(capacity);freqMap = new HashMap<>();}public int get(int key) {if (kvMap.get(key) == null) {return -1;}Node node = kvMap.get(key);// 當前節點是最低頻率且此時最低頻率鏈表只有該節點,最低頻率增加if (node.freq == minFreq && node.prev.prev == null && node.next.next == null) {minFreq++;}// 頻率加一node.freq++;// 從舊頻率對應鏈表刪除deleteNode(node);// 插入到新頻率鏈表尾部if (freqMap.get(node.freq) == null) {initFreqMap(node.freq);}addTail(node, freqMap.get(node.freq)[1]);return node.value;}public void put(int key, int value) {Node node = new Node();if (kvMap.get(key) != null) {node = kvMap.get(key);// 當前節點是最低頻率且此時最低頻率只有該節點,最低頻率增加if (node.freq == minFreq && node.prev.prev == null && node.next.next == null) {minFreq++;}// 頻率加一node.freq++;node.value = value;// 從舊頻率對應鏈表刪除deleteNode(node);} else {// 超出容量,移除最小頻率的節點if (capacity == 0) {Node head = freqMap.get(minFreq)[0];kvMap.remove(head.next.key);deleteNode(head.next);capacity = 1;}node.freq = 1;node.key = key;node.value = value;kvMap.put(key, node);minFreq = 1;capacity--;}if (freqMap.get(node.freq) == null) {initFreqMap(node.freq);}// 插入到新頻率鏈表尾部addTail(node, freqMap.get(node.freq)[1]);}public void initFreqMap(int freq) {Node head = new Node();Node tail = new Node();head.next = tail;tail.prev = head;Node[] arr = new Node[] {head, tail};freqMap.put(freq, arr);}public void deleteNode(Node node) {Node prevNode = node.prev;Node nextNode = node.next;prevNode.next = nextNode;nextNode.prev = prevNode;node.prev = null;node.next = null;}public void addTail(Node node, Node tail) {Node prevNode = tail.prev;prevNode.next = node;node.prev = prevNode;node.next = tail;tail.prev = node;}
}class Node {int freq;int key;int value;Node prev;Node next;
}

關鍵點

  • 注意更新minFreq的值
  • 雙向鏈表的相關操作
  • 容量滿時插入節點需要對使用頻率最低的節點做刪除操作

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/90887.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/90887.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/90887.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

檢查輸入有效性(指針是否為NULL)和檢查字符串長度是否為0

檢查輸入有效性&#xff08;指針是否為NULL&#xff09;和檢查字符串長度是否為0 這兩個檢查針對的是完全不同的邊界情況&#xff0c;都是必要的防御性編程措施&#xff1a; 1. 空指針檢查 if(!src) 目的&#xff1a;防止解引用空指針場景&#xff1a;當調用者傳入 NULL 時風險…

Apache POI 的 HSSFWorkbook、SXSSFWorkbook和XSSFWorkbook三者的區別

HSSFWorkbook 專用于處理Excel 97-2003&#xff08;.xls&#xff09;格式的二進制文件。基于純Java實現&#xff0c;所有數據存儲在內存中&#xff0c;適合小規模數據&#xff08;通常不超過萬行&#xff09;。內存占用較高&#xff0c;但功能完整&#xff0c;支持所有舊版Exce…

冷凍電鏡重構的GPU加速破局:從Relion到CryoSPARC的并行重構算法

點擊 “AladdinEdu&#xff0c;同學們用得起的【H卡】算力平臺”&#xff0c;H卡級別算力&#xff0c;按量計費&#xff0c;靈活彈性&#xff0c;頂級配置&#xff0c;學生專屬優惠。 一、冷凍電鏡重構的算力困局 隨著單粒子冷凍電鏡&#xff08;cryo-EM&#xff09;分辨率突破…

算法學習筆記:16.哈希算法 ——從原理到實戰,涵蓋 LeetCode 與考研 408 例題

在計算機科學中&#xff0c;哈希算法&#xff08;Hash Algorithm&#xff09;是一種將任意長度的輸入數據映射到固定長度輸出的技術&#xff0c;其輸出稱為哈希值&#xff08;Hash Value&#xff09;或散列值。哈希算法憑借高效的查找、插入和刪除性能&#xff0c;在數據存儲、…

16018.UE4+Airsim仿真環境搭建超級詳細

文章目錄 1 源碼下載2 下載安裝軟件2.1 安裝 UE4 軟件2.2 安裝visual studio 20223 編譯airsim源碼4 進入AirSim工程,打開工程5 UE4 工程創建5.1 下載免費場景 CityPark,并創建工程5.2 工程編譯5.2.1 將airsim 插件拷貝到 UE4工程路徑中5.2.2 修改工程配置文件5.2.3 創建c++類…

Python 實戰:構建 Git 自動化助手

在多項目協作、企業級工程管理或開源社區維護中&#xff0c;經常面臨需要同時管理數十甚至上百個 Git 倉庫的場景&#xff1a;多倉庫需要統一 pull 拉取更新定期向多個項目批量 commit 和 push自動備份 Git 項目批量拉取私有倉庫并管理密鑰為解決這類高頻、重復、機械性工作&am…

【PTA數據結構 | C語言版】出棧序列的合法性

本專欄持續輸出數據結構題目集&#xff0c;歡迎訂閱。 文章目錄題目代碼題目 給定一個最大容量為 m 的堆棧&#xff0c;將 n 個數字按 1, 2, 3, …, n 的順序入棧&#xff0c;允許按任何順序出棧&#xff0c;則哪些數字序列是不可能得到的&#xff1f;例如給定 m5、n7&#xf…

【LangGraph】create_react_agent 方法詳細解釋

create_react_agent 方法詳細解釋 create_react_agent 方法是一個在 LangGraph 中創建 React 代理的核心函數,接下來我們將一起探討這個函數的作用、參數、返回值以及工作原理。 @_convert_modifier_to_prompt def create_react_agent(model: Union[str, LanguageModelLike]…

【時間之外】塵封的智能套件復活記

目錄 塵封的獎品 初次觸網的挫敗 客服只會誘導消費 意外發現的生機 真相與反思 塵封的獎品 五年前那個蟬鳴陣陣的夏日&#xff0c;我抱著創新比賽特等獎的獎品禮盒走下領獎臺時&#xff0c;絕對想不到這份榮譽會衍生出如此曲折的故事。禮盒里靜靜躺著的智能家居套裝&…

從零開始學前端html篇1

1基本結構<!DOCTYPE html> <html><head><title>this is a good website</title></head><body><h1>hello!</h1></body> </html>運行效果如下&#xff08;編輯器提示waings:"缺少所需的 lang 特性"…

Redis Cluster 手動部署(小白的“升級打怪”成長之路)

目錄 一、環境規劃 二、基礎環境 1、創建配置目錄 2、生成配置文件 3、修改監聽端口 4、修改數據目錄 5、修改日志目錄 6、修改PID文件目錄 7、修改保護模式 8、修改進程運行模式 9、修改監聽地址 10、生成集群配置 11、啟動服務 三、構建集群 1、將其他節點加入…

【Java入門到精通】(三)Java基礎語法(下)

一、面向對象&#xff08;類和對象&#xff09;1.1 萬事萬物皆對象類&#xff1a;對對象向上抽取出像的部分、公共的部分以此形成類&#xff0c;類就相當于一個模板。對象&#xff1a;模板下具體的產物可以理解為具體對象&#xff0c;對象就是一個一個具體的實例&#xff0c;就…

Java文件傳輸要點

Java文件傳輸要點 一、前端 <form action"/upload" method"post" enctype"multipart/form-data"> <!--<form action"/upload" method"post">-->姓名: <input type"text" name"username…

Spring Boot 中使用 Lombok 進行依賴注入的示例

Spring Boot 中使用 Lombok 進行依賴注入的示例 下面我將展示 Spring Boot 中使用 Lombok 進行依賴注入的不同方式&#xff0c;包括構造器注入、屬性注入和 setter 方法注入&#xff0c;以及相應的測試用例。 1. 構造器注入&#xff08;推薦方式&#xff09; import lombok.Req…

vue3+vit+vue-router路由,側邊欄菜單,面包屑導航設置層級結構

文章目錄注意效果圖目錄結構代碼vite.config.ts需要配置路徑別名符號main.tsApp.vueBreadcrumb.vue面包屑組件menus.ts// src/router/index.ts其他文件注意 目錄結構僅供參考DefaultLayout.vue 沒有用到&#xff0c;我直接寫在APP文件中vux-store我也沒有用到&#xff0c;單獨…

使用Selenium自動化獲取抖音創作者平臺視頻數據

前言 在當今短視頻盛行的時代&#xff0c;抖音作為國內領先的短視頻平臺&#xff0c;吸引了大量內容創作者。對于創作者而言&#xff0c;了解自己發布的視頻表現&#xff08;如播放量、發布時間等&#xff09;至關重要。本文將介紹如何使用Python的Selenium庫來自動化獲取抖音…

SpringCloud之Eureka

SpringCloud之Eureka 推薦參考&#xff1a;https://www.springcloud.cc/spring-cloud-dalston.html#_service_discovery_eureka_clients 1. 什么是Eureka Eureka 用于簡化分布式系統的服務治理&#xff0c;基于REST的服務&#xff0c;用于服務的注冊與發現。通過注冊發現、客戶…

squash壓縮合并

要將test分支的多次提交合并到dev分支并壓縮為一個commit&#xff0c;核心是使用 git merge --squash 命令&#xff08;壓縮合并&#xff09;&#xff0c;具體步驟如下&#xff1a; 詳細步驟&#xff1a; 1. 切換到dev分支并拉取最新代碼先確保本地dev分支是最新的&#xff0c;…

飛書CEO謝欣:挑戰巨頭,打造AI新時代的Office

引言&#xff1a;飛書要做AI時代辦公協作的逐夢者與破局者。文 | 大力財經在AI浪潮席卷的當下&#xff0c;企業對AI既滿懷期待又充滿焦慮。“AI到底能不能用&#xff1f;AI到底怎么用&#xff1f;”成為縈繞在眾多企業心頭的難題。7月9日召開的飛書未來無限大會&#xff0c;飛書…

React 組件中怎么做事件代理?它的原理是什么?

在 React 組件中&#xff0c;**事件代理&#xff08;Event Delegation&#xff09;**其實是 React 內部實現的一部分&#xff0c;開發者通常無需手動實現事件代理&#xff0c;但理解它的原理和使用方式對于優化性能和掌握底層機制非常重要。一、React 中事件代理的原理React 使…