力扣(O(1) 時間插入、刪除和獲取隨機元素)

一、題目分析

在這里插入圖片描述

(一)功能需求

我們需要實現 RandomizedSet 類,包含以下功能:

  • RandomizedSet():初始化數據結構。
  • bool insert(int val):當元素 val 不存在時,插入該元素并返回 true;若已存在,返回 false 。
  • bool remove(int val):當元素 val 存在時,移除該元素并返回 true;若不存在,返回 false 。
  • int getRandom():隨機返回現有集合中的一個元素,每個元素被返回的概率相同,且調用時集合至少有一個元素 。

(二)核心挑戰

要讓插入、刪除、獲取隨機元素操作的平均時間復雜度都達到 O(1) 。常規的數據結構往往難以單獨滿足這些要求,比如哈希表雖能高效插入和刪除,但難以高效隨機獲取;動態數組便于隨機獲取,但插入和刪除(尤其是中間元素)的時間復雜度較高。所以需要結合兩者的優勢來實現。

二、算法思想:哈希表 + 動態數組的協同運用

(一)哈希表(Map)的作用

使用 Map<Integer, Integer> 來存儲元素 val 以及它在動態數組中的索引。這樣可以:

  • 插入元素時,快速判斷元素是否已存在(通過 map.containsKey(val) ),時間復雜度為 O(1) 。
  • 刪除元素時,快速獲取元素在動態數組中的位置,為后續在動態數組中高效刪除元素做準備,時間復雜度為 O(1) 。

(二)動態數組(List)的作用

使用 List 來存儲元素的值,方便進行隨機獲取操作。因為要實現隨機獲取元素且每個元素概率相同,我們可以利用 Random 類生成隨機索引(范圍是 0 到 list.size() - 1 ),然后通過 list.get(randomIndex) 快速獲取元素,時間復雜度為 O(1) 。

(三)刪除操作的優化

刪除元素時,直接刪除動態數組中間的元素時間復雜度會是 O(n) (需要移動元素 )。為了優化這個操作,我們采用“交換刪除”的策略:

  1. 獲取要刪除元素 val 在動態數組中的索引 reNumIndex ,以及動態數組最后一個元素 lastNum 。
  2. 將動態數組中 reNumIndex 位置的元素替換為 lastNum 。
  3. 更新 lastNum 在哈希表中的索引為 reNumIndex 。
  4. 刪除動態數組的最后一個元素(時間復雜度 O(1) ),并從哈希表中移除 val 。這樣就將刪除操作的時間復雜度優化到了 O(1) 。

三、代碼實現與詳細注釋

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;class RandomizedSet {// 哈希表,鍵為元素值,值為該元素在 numsList 中的索引Map<Integer, Integer> map; // 動態數組,存儲元素的值,用于隨機獲取List<Integer> numsList; // 用于生成隨機索引Random random; // 構造函數,初始化數據結構public RandomizedSet() {map = new HashMap<>();numsList = new ArrayList<>();random = new Random();}// 插入元素操作public boolean insert(int val) {// 判斷元素是否已存在于哈希表中if (map.containsKey(val)) { return false; // 已存在,返回 false} else {// 將元素 val 與它在 numsList 中的索引(當前 numsList 的長度,因為即將添加到末尾)存入哈希表map.put(val, numsList.size()); // 將元素添加到 numsList 末尾numsList.add(val); return true; // 插入成功,返回 true}}// 刪除元素操作public boolean remove(int val) {// 判斷元素是否存在于哈希表中if (map.containsKey(val)) { // 獲取動態數組最后一個元素的值int lastNum = numsList.get(numsList.size() - 1); // 獲取要刪除元素 val 在 numsList 中的索引int reNumIndex = map.get(val); // 將 numsList 中 reNumIndex 位置的元素替換為 lastNumnumsList.set(reNumIndex, lastNum); // 更新 lastNum 在哈希表中的索引為 reNumIndexmap.put(lastNum, reNumIndex); // 刪除 numsList 的最后一個元素(時間復雜度 O(1) )numsList.remove(numsList.size() - 1); // 從哈希表中移除要刪除的元素 valmap.remove(val); return true; // 刪除成功,返回 true} else {return false; // 元素不存在,返回 false}}// 隨機獲取元素操作public int getRandom() {// 生成一個 0 到 numsList.size() - 1 范圍內的隨機索引int randomIndex = random.nextInt(numsList.size()); // 根據隨機索引獲取元素并返回return numsList.get(randomIndex); }
}/*** Your RandomizedSet object will be instantiated and called as such:* RandomizedSet obj = new RandomizedSet();* boolean param_1 = obj.insert(val);* boolean param_2 = obj.remove(val);* int param_3 = obj.getRandom();*/

四、復雜度分析

(一)時間復雜度

  • 插入操作(insert):主要操作是哈希表的 containsKey 和 put ,以及動態數組的 add 操作。哈希表的這兩個操作時間復雜度是 O(1) ,動態數組 add 操作(在末尾添加)時間復雜度也是 O(1) ,所以插入操作平均時間復雜度為 O(1) 。
  • 刪除操作(remove):通過“交換刪除”的優化,哈希表的 containsKey、get、put、remove 操作,以及動態數組的 get、set、remove(末尾刪除 )操作,時間復雜度都是 O(1) ,所以刪除操作平均時間復雜度為 O(1) 。
  • 隨機獲取操作(getRandom):生成隨機索引和動態數組的 get 操作時間復雜度都是 O(1) ,所以該操作平均時間復雜度為 O(1) 。

(二)空間復雜度

哈希表存儲了 n 個元素(n 是集合中元素的數量 ),空間復雜度為 O(n) ;動態數組也存儲了 n 個元素,空間復雜度為 O(n) ;Random 類占用常數空間。所以總的空間復雜度為 O(n) ,n 是集合中元素的最大數量。

O(1) 時間插入、刪除和獲取隨機元素這道題,通過巧妙結合哈希表和動態數組,充分發揮了兩者的優勢,成功實現了插入、刪除、隨機獲取操作平均時間復雜度為 O(1) 的需求。其中刪除操作的“交換刪除”策略,更是優化時間復雜度的關鍵。

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

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

相關文章

前端開發的面試自我介紹與準備

前端面試自我介紹不知道怎么說的&#xff0c;直接參考下面的模板&#xff0c;然后換成你的經歷 自我介紹控制在1分鐘左右&#xff0c;千萬不要說的太久&#xff0c;面試官會煩的&#xff0c;但是又不好意思打斷你 切記面試是人和人面對面的交流&#xff0c;要有&#xff0c;面試…

10、系統規劃與分析

一、系統規劃步驟系統規劃步驟對現有系統進行初步調查分析和確定系統目標分析子系統的組成和基本功能擬定系統的實施方案擬定系統的可行性研究指定系統建設方案系統規劃階段的產出物&#xff1a;可行性研究報告、系統設計任務書。習題1、擬定系統的實施方案是在系統規劃階段完成…

Nginx學習筆記(六)—— Nginx反向代理

&#x1f4da;Nginx學習筆記&#xff08;六&#xff09;—— Nginx反向代理 &#x1f4cc; 一、反向代理核心概念 本質原理&#xff1a; #mermaid-svg-UkFRDp2Ut7MK5T2N {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-s…

三伍微電子GSR2406 IoT FEM 2.4G PA 射頻前端模組芯片

三伍微電子GSR2406 IoT FEM 2.4G PA 射頻前端模組芯片規格書Product Description The GSR2406 is a high-performance, fully integrated RF front-end module (FEM) designed for Zigbee technology, Thread, and Bluetooth (including low energy) applications. The GSR2406…

開發避坑指南(24):RocketMQ磁盤空間告急異常處理,CODE 14 “service not available“解決方案

異常信息 Caused by: org.apache.rocketmq.client.exception.MQBrokerException: CODE: 14 DESC: service not available now, maybe disk full, CL: 0.94 CQ: 0.94 INDEX: 0.94, maybe your broker machine memory too small.異常背景 一個項目里面用到了rocketmq&#x…

開源WAF新標桿:雷池SafeLine用語義分析重構網站安全邊界

文章目錄前言【視頻教程】1.安裝Docker2.本地部署SafeLine3.使用SafeLine4.cpolar內網穿透工具安裝5.創建遠程連接公網地址6.固定Uptime Kuma公網地址前言 當個人或企業站點上線后面臨的首要威脅往往來自網絡攻擊——據統計&#xff0c;超過60%的Web應用漏洞利用嘗試在流量到達…

Mac M1探索AnythingLLM+SearXNG

SearXNG 能聚合來自多達 200 多個搜索服務&#xff0c;可私有化部署&#xff0c;并提供了靈活自定義選項。 AnythingLLMSearXNG&#xff0c;剛好能解決AnythingLLM因為網絡限制導致web search不可用的問題。 1 安裝docker 下載mac m1版本的docker并安裝。 https://docs.dock…

模式設計:策略模式及其應用場景

簡介 策略模式(Strategy Pattern)是一種行為型設計模式,它允許在運行時動態選擇算法或行為。核心思想是將算法封裝成獨立的類(策略),使它們可以相互替換,讓算法的變化獨立于使用它的客戶端。 核心思想 解耦:將算法的定義與使用分離。每個算法封裝起來,使它們可以互…

Squash Merge(壓縮合并)和Rebase Merge(變基合并)介紹

文章目錄**1. Squash Merge&#xff08;壓縮合并&#xff09;****定義****操作步驟****特點****優點****缺點****2. Rebase Merge&#xff08;變基合并&#xff09;****定義****操作步驟****特點****優點****缺點****3. 對比總結****4. 選擇建議****5. 示例場景****Squash Merg…

Linux編程 —— framebuffer

一、framebuffer概念framebuffer&#xff1a;幀緩沖&#xff0c;幀緩存技術Linux內核專門為圖形化顯示提供的一套應用程序接口。二、基本操作步驟1. 打開顯示設備(/dev/fb0) 2. 獲取顯示設備相關參數&#xff08;分辨率&#xff0c;像素格式&#xff09;---》ioctl 3. 建立顯存…

文件編輯html

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>文件行內容編輯器</title><script src&…

具有熔斷能力和活性探測的服務負載均衡解決方案

一、整體架構設計 1.核心組件 負載均衡器&#xff1a;負責選擇可用的服務節點健康檢查器&#xff1a;定期檢測服務節點的可用性服務節點管理&#xff1a;維護所有可用節點的狀態信息 2.負載均衡策略 輪詢(Round Robin)隨機(Random)加權輪詢(Weighted Round Robin)最少連接(Leas…

技術演進中的開發沉思-62 DELPHI VCL系列:VCL下的設計模式

今天聊聊設計模式&#xff0c;當然這個章節目前僅限于DELPHI VCL,因為接下來梳理的Factory/Factory Method、Bootstrap 和 ForEach 這三種設計樣例&#xff0c;看似獨立&#xff0c;卻在實際開發中相互配合&#xff0c;共同構建起高效、靈活的程序架構。在 DELPHI VCL 開發的技…

Docker 101:面向初學者的綜合教程

掌握 Docker 已成為軟件開發中的一項關鍵技能。本教程探討了容器化的世界&#xff0c;包括其核心概念、優缺點&#xff0c;以及開始使用容器化的分步指南。 無論是 Docker 的新手&#xff0c;還是希望復習基礎知識的更有經驗的開發人員&#xff0c;本指南都能滿足需求。 什么…

RTOS YAFFS

在 YAFFS (Yet Another Flash File System) 的語境中&#xff0c;“Check Point” 并不是一個標準的、核心的官方術語。它更可能是對 YAFFS 關鍵機制 Summary 或 Checkpointing 功能的非正式表述或理解偏差。其核心含義是指 YAFFS 在特定時刻保存文件系統關鍵元數據的狀態&…

【SpringBoot系列-02】自動配置機制源碼剖析

【SpringBoot系列-02】自動配置機制源碼剖析 咱們天天用Spring Boot&#xff0c;一個SpringBootApplication注解扔進去&#xff0c;啥配置都不用寫&#xff0c;項目就跑起來了。你有沒有過這種疑惑&#xff1a;那些DispatcherServlet、DataSource是從哪冒出來的&#xff1f;今天…

51單片機-51單片機最小系統

本章概述思維導圖&#xff1a;51單片機最小系統51單片機最小系統是51系列單片機&#xff08;如AT89C51、STC89C52等&#xff09;能夠獨立工作的最簡電路配置&#xff0c;它為單片機提供了運行所需的基本條件。51單片機最小系統板是嵌入式系統開發的基礎平臺&#xff0c;集成了單…

git學習1

目錄引入版本控制集中式和分布式版本控制git工作機制代碼托管中心Git常用命令設置用戶簽名初始化本地庫查看庫狀態add和提交版本穿梭git分支操作分支定義分支好處分支操作查看分支創建分支切換分支分支合并&#x1f495;?&#x1fa77;合并沖突git團隊協作團隊內協作跨團隊協作…

redis原理篇--Dict

Dict數據結構一、Redis字典的核心組件Redis字典由三部分構成&#xff1a;dictht&#xff08;哈希表&#xff09;&#xff1a;存儲桶數組與元數據dictEntry&#xff08;哈希節點&#xff09;&#xff1a;存儲鍵值對dict&#xff08;字典主體&#xff09;&#xff1a;包含雙哈希表…

靜態路由主備切換

在網絡中&#xff0c;靜態路由的主備切換是實現網絡冗余的基礎方案之一&#xff0c;通過配置不同優先級的靜態路由&#xff0c;確保主用路徑故障時&#xff0c;流量能自動切換到備用路徑&#xff0c;提升網絡可靠性。以下從知識講解和實驗配置兩部分詳細說明。一、靜態路由主備…