146. LRU緩存

題目:
請你設計并實現一個滿足 LRU (最近最少使用) 緩存 約束的數據結構。
實現 LRUCache 類:
LRUCache(int capacity) 以 正整數 作為容量 capacity 初始化 LRU 緩存
int get(int key) 如果關鍵字 key 存在于緩存中,則返回關鍵字的值,否則返回 -1 。
void put(int key, int value) 如果關鍵字 key 已經存在,則變更其數據值 value ;如果不存在,則向緩存中插入該組 key-value 。如果插入操作導致關鍵字數量超過 capacity ,則應該 逐出 最久未使用的關鍵字。
函數 get 和 put 必須以 O(1) 的平均時間復雜度運行。

解題思路:
閱讀了靈神的題解之后,總結一下自己的理解。
想象有一堆書很妙。
對于get:想閱讀一本書,那么我就需要從這堆書里面把書取出來,讀完之后再放到最上面。這里就涉及到三個步驟:
1、先從這一堆書中找到這本書
2、從這堆書里拿出這本書
3、再將這本書放回到這堆書最上面

對于put:想添加一本書,首先需要判斷有沒有這本書,如果有,就把他拿出來,更新value,再放回這堆書最上面。如果沒有,就先判斷這堆書容量是否以達到最大容量,如果達到了,就丟棄最下面那本書,因為最下面那本書代表最久每閱讀的書了,然后再將這本新書放到書堆上面。這里也涉及三個步驟:
1、首先獲取這本書,如果有就更新value。注意在獲取這本書的過程也要包含找書、拿書、再放書,所以可以封裝成一個方法。
2、如果沒有這本書,則判斷容量是否達到閾值。如果達到,則刪除最下面一本書。
3、將這本新書放到書堆最上面。

那么現在的問題就是,該用什么數據結構來表示這堆書呢?
題目中的要求是get和put的時間復雜度都要是O(1),可以想到用鏈表來實現,因為如果我們知道這本書在鏈表中的位置,我們可以在O(1)的時間復雜度刪除它再將它添加到鏈表頭部。
那為什么要使用雙向鏈表呢?
因為我們有一個刪除最下面那本書的過程,也就是刪除鏈表尾節點,如果我們用單向鏈表的話,我們需要先遍歷鏈表找到尾節點,就會導致時間復雜度不滿足要求。
而添加一個哨兵節點是為了不用特殊處理鏈表為空的情況

那為什么還需要有一個哈希表呢
注意我在上面說的“如果我們知道這本書在鏈表中的位置,我們可以在O(1)的時間復雜度刪除它再將它添加到鏈表頭部”。
我們一開始肯定是不知道這本書在鏈表中的具體位置的,我們就需要先遍歷鏈表找到這本書,這樣的話時間復雜度也是不符合要求的。
所以,我們需要用key能夠在O(1)的時間復雜度內,找到這本書的位置,那么就可以用哈希表來存儲key到鏈表節點的映射關系。

代碼:

class LRUCache {private static class Node{int key;int value;Node pre;Node next;public Node(int key, int value){this.key = key;this.value = value;}  }private final int capacity;private final Node dummy = new Node(0, 0);private final Map<Integer, Node> keyToNode = new HashMap<>();public LRUCache(int capacity) {this.capacity = capacity;dummy.next = dummy;dummy.pre = dummy;}public int get(int key) {Node node = getNode(key);return node == null ? -1 : node.value;}public void put(int key, int value) {Node node = getNode(key);if(node != null){node.value = value;return;}// 如果關鍵容量達到capacity,則刪除最久未使用的if(keyToNode.size() == capacity){Node lastNode = dummy.pre;keyToNode.remove(lastNode.key);remove(lastNode);}node = new Node(key, value);keyToNode.put(key, node);putFirst(node);}private Node getNode(int key){if(!keyToNode.containsKey(key)){return null;}Node node = keyToNode.get(key);remove(node);putFirst(node);return node;}private void remove(Node node){node.pre.next = node.next;node.next.pre = node.pre;}private void putFirst(Node node){node.next =  dummy.next;node.pre = dummy;dummy.next.pre = node;dummy.next = node;}
}/*** Your LRUCache object will be instantiated and called as such:* LRUCache obj = new LRUCache(capacity);* int param_1 = obj.get(key);* obj.put(key,value);*/

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

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

相關文章

第二十節:3D文本渲染 - 字體幾何體生成與特效

第二十節&#xff1a;3D文本渲染 - 字體幾何體生成與特效 TextGeometry深度解析與高級文字效果實現1. 核心概念解析 1.1 3D文字渲染技術對比技術原理優點缺點TextGeometry將字體輪廓轉換為3D網格真實3D效果&#xff0c;支持材質性能開銷大&#xff0c;內存占用高Canvas紋理將文…

zzz‘sJava知識點概括總結

類型轉化 字符串&#xff1a;c語言&#xff1a;char Java&#xff1a;string 表達式值的類型由最高類型決定&#xff1a; 取值范圍&#xff1a;byte<short<int<long<float<double&#xff08;且運算時byte和short都是轉化為int類型進行計算防止數據溢出&…

SONiC 之 Testbed(2)Ansible

Ansible 是一款由 Red Hat 主導開發的 開源自動化工具&#xff0c;專注于 配置管理、應用部署、任務編排和IT自動化。它基于 無代理&#xff08;Agentless&#xff09;架構&#xff0c;通過 SSH&#xff08;默認&#xff09;或 WinRM 協議與目標設備通信&#xff0c;無需在被控…

瑞芯微RK3568與君正X2600e平臺Linux系統CS創世SD NAND應用全解析與驅動架構詳解

前言 今天就瑞芯微平臺和北京君正平臺下的linux系統中關于CS創世 SD NAND的使用做一些經驗的分享&#xff0c;如有不正&#xff0c;請批評指正&#xff1b; 采用的開發板是RK3568和x2600e&#xff0c;ubuntu版本是20.04&#xff0c;交叉編譯工具鏈是aarch64-linux-gnu-和mips…

深入解析 Flink Function

RichFunctionFunction只是個標記接口public interface Function extends java.io.Serializable {}RichFunction 的核心語義是為用戶定義的函數&#xff08;UDF&#xff09;提供生命周期管理和運行時上下文訪問的能力。任何一個普通的 Flink Function 接口&#xff08;例如 MapF…

JMeter —— 壓力測試

目錄 常用的性能指標 一、吞吐量類指標 二、響應時間類指標 三、資源利用率指標 JMeter 一、JMeter 簡介 二.下載安裝JMeter&#xff1a; 三.如何使用JMeter&#xff1a; 壓力測試考察當前軟硬件環境下系統所能承受的最大負荷并幫助找出系統瓶頸所在。壓測都是為了系統…

Transformer在哪?做了權重共享?

1、什么是權值共享權重共享是指在模型的不同層之間復?相同的參數。這可以減少模型的總體參數數量&#xff0c;并使得模型在訓練時更容易學習。2、在Transformer中的應用常見的做法是共享詞嵌入層&#xff08;embedding layer&#xff09;和輸出層&#xff08;output layer&…

將 agents 連接到 Elasticsearch 使用模型上下文協議 - docker

我們在之前的文章 “將 agents 連接到 Elasticsearch 使用模型上下文協議” 及 “使用 MCP 將代理連接到 Elasticsearch 并對索引進行查詢” 詳述了如何使用 Elasticsearch MCP server 來和我們的 Elasticsearch 進行對話。細心的開發者可能已經注意到我們的 Elasticsearch MCP…

Shell 編程基礎與實踐要點梳理

目錄 前言 一、認識 Shell 1.1 Shell 的定義與作用 1.2 Shell 解釋器 二、Shell 腳本入門 2.1 編寫 Shell 腳本 2.2 賦予執行權限與執行腳本 三、Shell 變量 3.1 變量定義與規則 3.2 變量使用與操作 3.3 變量類型 四、Shell 字符串 4.1 字符串定義方式 4.2 字符串…

Python自動化測試完整教程:pytest + selenium實戰

目錄 前言環境搭建pytest基礎教程selenium基礎教程pytest selenium實戰項目頁面對象模式(POM)測試報告生成持續集成配置最佳實踐和進階技巧總結 前言 自動化測試是現代軟件開發中不可或缺的一環。Python作為一門簡潔優雅的編程語言&#xff0c;配合pytest測試框架和seleniu…

APM 系列(一):Skywalking 與 Easyearch 集成

概述 SkyWalking 是一個開源的可觀測性平臺&#xff0c;用于收集、分析、聚合和可視化服務和云原生基礎設施的數據。SkyWalking 提供了一種簡單的方法&#xff0c;即使在云之間也能保持對分布式系統的清晰視圖。它是一個現代的 APM&#xff0c;專門為云原生、基于容器的分布式…

使用 AD 帳戶從 ASP.NET 8 容器登錄 SQL Server 的 Kerberos Sidecar

我最近在做一個項目,需要將一個 ASP.NET 8 Web API 應用程序容器化,該應用程序需要與本地運行的 SQL Server 數據庫進行通信。我們決定將 ASP.NET 8 容器定位到 Linux 系統,因此必須與運行在 Windows AD 域中的數據庫進行通信。 問題 我們之前的設置是使用 IIS 在 Windows …

More Effective C++ 條款11:禁止異常流出析構函數之外

More Effective C 條款11&#xff1a;禁止異常流出析構函數之外核心思想 在C中&#xff0c;析構函數絕對不允許拋出異常。如果異常從析構函數中傳播出去&#xff0c;可能會導致程序立即終止或未定義行為&#xff0c;特別是在棧展開過程中處理已有異常時。通過捕獲并處理所有析構…

商超高峰客流統計誤差↓75%!陌訊多模態融合算法在智慧零售的實戰解析

原創聲明&#xff1a;本文為原創技術解析&#xff0c;核心技術參數、架構設計及實戰數據引用自 “陌訊技術白皮書”&#xff0c;技術方案與落地案例結合aishop.mosisson.com智慧零售數據聯動場景展開&#xff0c;禁止未經授權的轉載與商用。 一、行業痛點&#xff1a;智慧零售…

PyTorch實戰(2)——使用PyTorch構建神經網絡

PyTorch實戰&#xff08;2&#xff09;——使用PyTorch構建神經網絡0. 前言1. PyTorch 構建神經網絡初體驗1.1 使用 PyTorch 構建神經網絡1.2 神經網絡數據加載1.3 模型測試1.4 獲取中間層的值2. 使用 Sequential 類構建神經網絡3. PyTorch 模型的保存和加載3.1 模型保存所需組…

關于git的安裝(windows)

1.git的介紹 Git 是一個分布式版本控制系統&#xff0c;由 Linus Torvalds 在 2005 年為 Linux 內核開發而創建。它能夠高效地處理從小型到超大型項目的版本管理&#xff0c;具有以下特點&#xff1a; 分布式架構&#xff1a;每個開發者本地都有完整的倉庫副本高效性能&#…

Java后端開發?接口封裝器!

開發接口確實是Java后端開發中最核心、最可見的產出工作。“對入參校驗、處理業務邏輯、返回格式處理”——精準地描述了一個API接口的核心處理流程。 但這只是冰山之上最直觀的部分。一個專業、穩健、可擴展的后端系統&#xff0c;其復雜性和價值絕大部分隱藏在冰山之下。結合…

【沉浸式解決問題】NVIDIA 顯示設置不可用。 您當前未使用連接到NVIDIA GPU 的顯示器。

目錄一、問題描述二、環境版本三、原因分析四、解決方案一、問題描述 在看一篇cuda安裝的教程時&#xff0c;第一步是打開NVIDIA 控制面板&#xff0c;但是我打不開&#xff1a; NVIDIA 顯示設置不可用。 您當前未使用連接到NVIDIA GPU 的顯示器。 二、環境版本 設備&#xf…

牛客周賽 Round 106(小苯的方格覆蓋/小苯的數字折疊/ 小苯的波浪加密器/小苯的數字變換/小苯的洞數組構造/ 小苯的數組計數)

A 小苯的方格覆蓋思路&#xff1a;怎么擺第三行都是橫放的2*1&#xff1b;故若n為奇數&#xff0c;總格子數3n為奇數&#xff0c;無法被2整除&#xff0c;直接排除。#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<iostream> #include<bits/stdc…

高并發內存池(16)-三層緩存的回收過程

高并發內存池&#xff08;16&#xff09;-三層緩存的回收過程 內存池的回收過程是內存管理系統的關鍵環節&#xff0c;它通過分層協作和智能合并機制&#xff0c;確保內存高效重復利用。以下是完整的回收流程解析&#xff1a;一、回收觸發場景 ThreadCache回收&#xff1a;線程…