力扣面试经典算法150题:O(1) 时间插入、删除和获取随机元素

O(1) 时间插入、删除和获取随机元素

今天的题目是力扣面试经典150题中的数组的中等难度题: O(1) 时间插入、删除和获取随机元素。

题目链接:https://leetcode.cn/problems/insert-delete-getrandom-o1/description/?envType=study-plan-v2&envId=top-interview-150

问题描述

实现RandomizedSet 类:

RandomizedSet() 初始化 RandomizedSet 对象
bool insert(int val) 当元素 val 不存在时,向集合中插入该项,并返回 true ;否则,返回 false 。
bool remove(int val) 当元素 val 存在时,从集合中移除该项,并返回 true ;否则,返回 false 。
int getRandom() 随机返回现有集合中的一项(测试用例保证调用此方法时集合中至少存在一个元素)。每个元素应该有 相同的概率 被返回。
你必须实现类的所有函数,并满足每个函数的 平均 时间复杂度为 O(1) 。

  • 示例

    • 输入:
      [“RandomizedSet”, “insert”, “remove”, “insert”, “getRandom”, “remove”, “insert”, “getRandom”]
      [[], [1], [2], [2], [], [1], [2], []]
    • 输出:
      [null, true, false, true, 2, true, false, 2]
  • 解释:
    RandomizedSet randomizedSet = new RandomizedSet();
    randomizedSet.insert(1); // 插入 1,返回 true 表示成功插入
    randomizedSet.remove(2); // 尝试移除 2,返回 false 表示未找到
    randomizedSet.insert(2); // 插入 2,返回 true 表示成功插入
    randomizedSet.getRandom(); // 随机返回 1 或 2,这里假设返回 2
    randomizedSet.remove(1); // 移除 1,返回 true 表示成功移除
    randomizedSet.insert(2); // 尝试插入 2,返回 false 表示已存在
    randomizedSet.getRandom(); // 随机返回 2,因为现在集合中只有 2

题目分析

题目要求我们实现一个类,这个类可以写入,删除或随机获取某个元素,并且要求每个函数的平均时间复杂度为O(1)。

不要被要实现一个类迷惑,其实就是要求我们设计一个数据结构和函数算法,并且要求函数的时间复杂度在规定范围之内就行。

为了实现在 O(1) 时间内完成插入、删除和获取随机元素的操作,我们需要设计一种数据结构,能够快速定位元素的位置,并且在删除元素时不影响随机获取的性能。

解题思路

这个题目需要通过组合我们常用的数据结构来实现需求,考验的就是我们对常见的数据结构的理解与掌握。毕竟是中等难度的题目,能够正确理解掌握现有的数据结构并通过组合实现特定场景的优秀算法,已经是很不错了。

我们先梳理一下常见的数据结构:数组,链表,哈希表,队列,堆,栈。这些数据结构各有各的特点,这里不一一细讲,这东西细讲起来能不是一下两下能讲完的,目前我们需要知道的就是,想完成题目要求,我们需要在这些数据结构中组合使用。

看看题目中的要求,不存在时才能新增,存在时才能删除。也就是说,在执行这两个函数的时候,我们需要先知道元素在不在我们设定的数据结构中。

这个时候,哈希表说:老弟,这个我熟啊!

但是哈希表的新增与删除通常情况下是符合条件的,但是极端情况下是O(n)。此外,获取随机元素通常我们需要遍历整个哈希表才能实现,这个时间复杂度是O(n)。

假如我们在哈希表的基础上,加其他的数据结构来实现是不是就可行呢?因为之前我们就分析过,这个题目本身就是需要通过组合多种数据结构实现的。那么获取随机元素的同时,新增删除又能是O(1)的时间复杂度的,又有谁能?

数组:哥,你看看我啊!这里!

没错,数组,作为最常用并且最先认识的数据结构,有下标的情况下,随机获取是O(1)的复杂度,新增和删除最后一个元素也是O(1)的复杂度。

那么,使用data-index的键值对方式保存到哈希表中,将实际元素放入到数组中。是不是满足新增删除前的判断,并且新增,获取随机元素的时间复杂度都是O(1),唯一没满足的就是删除,因为我们不能保证每次都删除最后一位元素。但是,数组的修改方法,在有下标的时候,时间复杂度是O(1)。正所谓没有条件,创造条件也要上,我们直接把需要删除的元素修改到最后一位,再删除,是不是就变成删除最后一位元素,时间复杂度为O(1)了。

总结一下上面的分析内容:

  1. 哈希表 + 动态数组:使用哈希表来存储元素及其在数组中的位置,使用动态数组来存储实际的元素。
  2. 优化删除操作:为了保证删除操作能在 O(1) 时间内完成,可以将要删除的元素与数组的最后一个元素交换位置,然后删除最后一个元素。

那么,开始表演!

实际算法代码

以下是使用上述思路的 Java 实现:

import java.util.HashMap;
import java.util.Map;class RandomizedSet {private Map<Integer, Integer> valToIndex;private int[] values;private int size;public RandomizedSet() {valToIndex = new HashMap<>();// 初始容量values = new int[8];size = 0;}public boolean insert(int val) {if (valToIndex.containsKey(val)) return false;if (size == values.length) {resizeArray();}valToIndex.put(val, size);values[size] = val;size++;return true;}public boolean remove(int val) {if (!valToIndex.containsKey(val)) return false;int index = valToIndex.get(val);int lastElement = values[size - 1];values[index] = lastElement;valToIndex.put(lastElement, index);valToIndex.remove(val);size--;return true;}public int getRandom() {return values[(int) (Math.random() * size)];}private void resizeArray() {int[] newArray = new int[values.length * 2];System.arraycopy(values, 0, newArray, 0, values.length);values = newArray;}
}

结果

提交到力扣,通过测试:

在这里插入图片描述

总结

最后总结本题中比较重要的两步:

  1. 数据结构设计:使用哈希表和动态数组结合的方式,实现了 O(1) 时间复杂度的插入、删除和获取随机元素操作。
  2. 优化技巧:在删除操作中,通过交换元素位置来避免重新排序,从而保证了 O(1) 的时间复杂度。

其实题目考察的还是对基础数据结构的掌握,掌握的好这个题目难度确实不算很难,但是掌握不好,这种题目有没有暴力破解的解法,就会直接卡死,基础还是重要的啊。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/409671.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle问题笔记

ORA-28040 没有匹配的验证协议 问题出现场景oracle数据库为12c,应用使用的jdbc或客户端工具是11g版本一下&#xff0c;连接12c数据库时会报ora-28040错误。解决办法在Oracle服务端的$ORACLE_HOME/network/admin/sqlnet.ora文件中添加&#xff1a; SQLNET.ALLOWED_LOGON_VERSI…

第4章 汇编语言和汇编软件

第4章 汇编语言和汇编软件 该章主要介绍了汇编语言和汇编语言编译器的安装和使用。 汇编语言程序 该小节主要介绍了为什么要有汇编语言和汇编语言程序的一些基础写法。 书中有提到CPU有不同的架构&#xff0c;汇编语言有不同的风格&#xff0c;那么不同的CPU架构和不同的汇…

日常维护交换机,看看这些老网工怎么说

号主&#xff1a;老杨丨11年资深网络工程师&#xff0c;更多网工提升干货&#xff0c;请关注公众号&#xff1a;网络工程师俱乐部 晚上好&#xff0c;我的网工朋友。 交换机作为连接各个节点的核心设备&#xff0c;其稳定性和可靠性直接关系到整个网络系统的健康运行。 路由器…

vue开发区分开发环境和生产环境,以及预发布环境

vue开发区分开发环境和生产环境&#xff0c;以及预发布环境 在根目录创建 .env[mode] 文件&#xff0c;在项目执行 npm run dev 的时候vite会自动去读取.env.development文件里面的配置&#xff0c;执行npm runbuild进行打包之后也会自动将.env.production的内容打包进去&…

Kafka日志及常见问题

目录 1.Topic下的消息是如何存储的 1.1log文件追加记录所有消息 1.2index和timeindex加速读取日志信息 2.文件清理机制 2.1如何判断哪些日志文件过期了 2.2日志清理策略 3.Kafka的文件高效读写机制 3.1Kafka的文件结构 3.2顺序写磁盘 3.3零拷贝 3.3.1传统IO 3.3.2m…

【硬件操作入门】2--GPIO与门电路、二极管三极管、LED电路与操作

【硬件操作入门】2–GPIO与门电路&#xff08;二极管&三极管&#xff09;、LED电路与操作 文章目录 【硬件操作入门】2--GPIO与门电路&#xff08;二极管&三极管&#xff09;、LED电路与操作一、GPIO与门电路1.1、GPIO的应用1.2、GPIO引脚操作1.2.1 设置引脚为GPIO功能…

加速网络体验,Squid缓存代理:让浏览如飞,畅享无限网络速度!

作者简介&#xff1a;我是团团儿&#xff0c;是一名专注于云计算领域的专业创作者&#xff0c;感谢大家的关注 座右铭&#xff1a; 云端筑梦&#xff0c;数据为翼&#xff0c;探索无限可能&#xff0c;引领云计算新纪元 个人主页&#xff1a;团儿.-CSDN博客 目录 前言: squ…

[数据集][目标检测]建筑工地楼层空洞检测数据集VOC+YOLO格式2588张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;2588 标注数量(xml文件个数)&#xff1a;2588 标注数量(txt文件个数)&#xff1a;2588 标注…

springboot项目读取 resources 目录下的文件的9种方式

1. 使用 ClassLoader.getResourceAsStream() 方法 InputStream inputStream getClass().getClassLoader().getResourceAsStream("file.txt"); 2. 使用 Class.getResourceAsStream() 方法 InputStream inputStream getClass().getResourceAsStream("/file.txt&…

JAVA-封装

目录 一、封装的概念 二、封装扩展之包 1. 包的概念 2.导入包中的类 3.自定义包 4.常见的包 三、访问限定符 在同一包中&#xff1a; 在不同包中&#xff1a;​编辑 一、封装的概念 面向对象程序三大特性&#xff1a;封装、继承、多态。而类和对象阶段&#xff0c;主…

网络安全——基础知识记忆梳理

1. SQL注入攻击 SQL注入攻击是一种常见的网络安全威胁&#xff0c;它利用Web应用程序中对用户输入的数据的不正确处理&#xff0c;攻击者可以在SQL查询中注入恶意代码&#xff0c;从而执行非授权的数据库操作。这种攻击方式可以导致数据泄漏、数据篡改、绕过认证等多种安全问题…

什么样的条件才会造就这样疯狂的末日期权?

今天带你了解什么样的条件才会造就这样疯狂的末日期权&#xff1f;末日期权一般是指期权合约快到期的一周或者最后三天&#xff0c;当然最后一天就是末日期权的疯狂。 末日期权是指那些接近到期日的期权。 由于剩余时间较短&#xff0c;这些期权的时间价值通常非常低&#xf…

MFC工控项目实例之七点击下拉菜单弹出对话框

承接专栏《MFC工控项目实例之六CFile添加菜单栏》 1、在SEAL_PRESSUREDlg.h文件中添加代码 class CSEAL_PRESSUREDlg : public CDialog { ...afx_msg void OnTypeManage(); ... } 2、在SEAL_PRESSUREDlg.cpp文件中添加代码 BEGIN_MESSAGE_MAP(CSEAL_PRESSUREDlg, CDialog)//…

快速排序与其例题

一、快速排序 1、简单介绍&#xff1a;快速排序&#xff08;Quick Sort&#xff09;是一种高效的排序算法&#xff0c;由计算机科学家Tony Hoare在1960年提出。它是基于分治法的排序算法&#xff0c;其基本思想和步骤如下&#xff1a; 基本概念 快速排序的核心思想是将待排序…

Debezium2.7 数据同步 MySQL/Oracle -- AI生成

Debezium是Red Hat开源的一个工具&#xff0c;用于实时捕获多种数据源&#xff08;包括MySQL、PostgreSQL、SQL Server、Oracle等&#xff09;的变更数据&#xff0c;并将这些数据作为事件流输出到Kafka等消息中间件中。通过Debezium&#xff0c;可以实现数据的实时同步和变更数…

【Qt】常用控件QCalendarWidget

常用控件QCalendarWidget的使用 QCalendarWidget表示一个日历 核心属性 属性说明 selectDate 当前选中的⽇期 minimumDate 最⼩⽇期 maximumDate 最⼤⽇期 firstDayOfWeek 每周的第⼀天(也就是⽇历的第⼀列) 是周⼏. gridVisible 是否显⽰表格的边框 selectionMode…

何为MethodHandles?

最近在梳理ThreadPoolExecutor&#xff0c;无意间看到其内部类Worker实现了一个名字叫做AbstractQueuedSynchronizer的抽象类。看到它&#xff0c;我便想起当年为了面试而疯狂学习这个知识点的场景。不过这种临时抱佛脚的行为&#xff0c;并未给我带来即时的收益。也是这次的疯…

软件上显示“mfc140.dll丢失”错误信息?那么mfc140.dll丢失该如何修复

mfc140.dll是 Microsoft Foundation Class (MFC) 库的一部分&#xff0c;这个库被用于基于 C 的 Windows 应用程序的开发。当 Windows 或软件上显示“mfc140.dll丢失”或“找不到 mfc140.dll”这类错误信息时&#xff0c;表示你的系统可能缺少与 Visual C 相关的组件或这些组件…

文本处理函数

1.文本的提取 left mid right 2.文本的查找与替换 replace&#xff0c;substitute 3.字符个数 len字符 lenb字节, office365好像没有此功能 4.数据的清理 clean , trim 5.找不同 exact

【Qt】多元素控件QTableWidget

多元素控件QTableWidget 使用QTableWidget表示一个表格控件&#xff0c;一个表格中包含若干行、每一个行又包含若干列。 表格中的每一个单元格&#xff0c;都是一个QTableWidget对象。 QTableWidget核心方法 方法说明 item(int row, int column) 根据⾏数列数获取指定的 Q…