代码训练LeetCode(23)随机访问元素

代码训练(23)LeetCode之随机访问元素

Author: Once Day Date: 2025年6月5日

漫漫长路,才刚刚开始…

全系列文章可参考专栏: 十年代码训练_Once-Day的博客-CSDN博客

参考文章:

  • 380. O(1) 时间插入、删除和获取随机元素 - 力扣(LeetCode)
  • 力扣 (LeetCode) 全球极客挚爱的技术成长平台

文章目录

      • 代码训练(23)LeetCode之随机访问元素
        • 1. 原题
        • 2. 分析
        • 3. 代码实现
        • 4. 总结

1. 原题

实现RandomizedSet 类:

  • RandomizedSet() 初始化 RandomizedSet 对象
  • bool insert(int val) 当元素 val 不存在时,向集合中插入该项,并返回 true ;否则,返回 false
  • bool remove(int val) 当元素 val 存在时,从集合中移除该项,并返回 true ;否则,返回 false
  • int getRandom() 随机返回现有集合中的一项(测试用例保证调用此方法时集合中至少存在一个元素)。每个元素应该有 相同的概率 被返回。

你必须实现类的所有函数,并满足每个函数的 平均 时间复杂度为 O(1)

提示:

  • -231 <= val <= 231 - 1
  • 最多调用 insertremovegetRandom 函数 2 * ``105
  • 在调用 getRandom 方法时,数据结构中 至少存在一个 元素。

示例 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 表示 1 被成功地插入。
randomizedSet.remove(2); // 返回 false ,表示集合中不存在 2 。
randomizedSet.insert(2); // 向集合中插入 2 。返回 true 。集合现在包含 [1,2] 。
randomizedSet.getRandom(); // getRandom 应随机返回 1 或 2 。
randomizedSet.remove(1); // 从集合中移除 1 ,返回 true 。集合现在包含 [2] 。
randomizedSet.insert(2); // 2 已在集合中,所以返回 false 。
randomizedSet.getRandom(); // 由于 2 是集合中唯一的数字,getRandom 总是返回 2 。
2. 分析

题目要求实现一个 RandomizedSet 类,该类包含以下方法:

  1. RandomizedSet() - 初始化对象。
  2. bool insert(int val) - 插入元素 val,如果元素不存在则插入并返回 true,否则返回 false
  3. bool remove(int val) - 移除元素 val,如果元素存在则移除并返回 true,否则返回 false
  4. int getRandom() - 随机返回集合中的一个元素。保证调用时集合中至少有一个元素,且每个元素有相同的被返回概率。

要求所有操作的平均时间复杂度为 O(1)。

为了满足该题目的要求,我们可以使用哈希表和数组组合的数据结构:

  1. 数组:用于存储元素,支持 O(1) 时间复杂度的随机访问。
  2. 哈希表:键为元素值,值为该元素在数组中的索引,支持 O(1) 时间复杂度的插入和删除操作。

方法实现细节:

插入 (insert):

  • 检查哈希表中是否已存在该元素。如果存在,返回 false
  • 将元素添加到数组末尾,并在哈希表中记录该元素的索引。
  • 返回 true

删除 (remove):

  • 检查哈希表中是否存在该元素。如果不存在,返回 false
  • 从数组中移除该元素,为了维持 O(1) 的复杂度,可以将数组最后一个元素移动到被删除元素的位置,并更新哈希表。
  • 从哈希表中删除该元素,并更新数组的大小。
  • 返回 true

获取随机元素 (getRandom):

  • 从数组中随机选择一个索引,然后返回该索引对应的元素。

性能优化关键点:

  • 内存管理:合理分配和释放内存是关键,尤其是在 randomizedSetCreaterandomizedSetFree 函数中。
  • 哈希冲突:避免哈希冲突可以提升性能,因此选择合适的哈希函数和冲突解决机制很重要。
3. 代码实现
struct entry {int val;int idx;struct entry* next;
};typedef struct {int size;                  // 当前元素数量int array[200000];         // 动态数组存储元素struct entry* map[100000]; // 哈希表存储元素到索引的映射
} RandomizedSet;RandomizedSet* randomizedSetCreate() {RandomizedSet* set = malloc(sizeof(RandomizedSet));memset(set, 0x0, sizeof(RandomizedSet));srand(time(NULL)); // 初始化随机种子return set;
}bool randomizedSetInsert(RandomizedSet* set, int val) {int key = val % 100000;struct entry** prev = &(set->map[key]);struct entry* item = set->map[key];while (item != NULL) {if (item->val == val) {return false;}prev = &(item->next);item = item->next;}item = malloc(sizeof(struct entry));item->val = val;item->next = NULL;item->idx = set->size;*prev = item;set->array[set->size] = val;set->size++;return true;
}bool randomizedSetRemove(RandomizedSet* set, int val) {int key = val % 100000;struct entry** prev = &(set->map[key]);struct entry* item = set->map[key];while (item != NULL) {if (item->val == val) {break;}prev = &(item->next);item = item->next;}if (item == NULL) {return false;}*prev = item->next;int idx = item->idx;free(item);if (idx == set->size - 1) {set->size--;return true;}int lastElement = set->array[set->size - 1];set->array[idx] = lastElement; // 将最后一个元素移动到被删除元素的位置set->size--;key = lastElement % 100000;item = set->map[key];while (item != NULL) {if (item->val == lastElement) {break;}item = item->next;}item->idx = idx;return true;
}int randomizedSetGetRandom(RandomizedSet* set) {int randomIndex = rand() % set->size;return set->array[randomIndex];
}void randomizedSetFree(RandomizedSet* set) {for (int i = 0; i < 100000; i++) {struct entry* item = set->map[i];while (item != NULL) {struct entry* temp = item->next;free(item);item = temp;}}free(set);
}

这段代码实现了一个 RandomizedSet 结构,它支持插入、删除、随机访问和销毁操作。下面分析每部分代码的功能和设计逻辑。

使用了两种数据结构:

  • 数组 (array):用于存储元素值,支持快速通过索引访问和随机访问。
  • 哈希表 (map):链地址法解决哈希冲突的哈希表,存储键为元素值,值为该元素在数组中的索引。

分配内存并初始化 RandomizedSet,其中 memset 用于初始化内存区域。

插入操作首先计算哈希键值,然后遍历链表检查元素是否已存在。如果不存在,创建新条目并加入链表和数组。

删除操作查找链表中的元素,然后从链表和数组中删除,同时更新相关元素的索引。

通过随机生成索引来从数组中获取元素。

释放哈希表中所有链表的内存以及 RandomizedSet 结构的内存。

4. 总结

这个题目主要考察数据结构的灵活应用和操作的优化。通过综合利用数组和哈希表,我们能够实现各种操作的平均 O(1) 时间复杂度。对于提升编程能力,重点是掌握各种数据结构的特点及其适用场景,以及如何根据需求选择和设计最合适的数据结构。

表和数组中删除,同时更新相关元素的索引。

通过随机生成索引来从数组中获取元素。

释放哈希表中所有链表的内存以及 RandomizedSet 结构的内存。

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

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

相关文章

C++面试5——对象存储区域详解

C++对象存储区域详解 核心观点:内存是程序员的战场,存储区域决定对象的生杀大权!栈对象自动赴死,堆对象生死由你,全局对象永生不死,常量区对象只读不灭。 一、四大地域生死簿 栈区(Stack) • 特点:自动分配释放,速度极快(类似高铁进出站) • 生存期:函数大括号{}就…

STM32 智能小车项目 L298N 电机驱动模块

今天开始着手做智能小车的项目了 在智能小车或机器人项目中&#xff0c;我们经常会听到一个词叫 “H 桥电机驱动”&#xff0c;尤其是常见的 L298N 模块&#xff0c;就是基于“双 H 桥”原理设计的。那么&#xff0c;“H 桥”到底是什么&#xff1f;为什么要用“双 H 桥”来驱动…

python项目如何创建docker环境

这里写自定义目录标题 python项目创建docker环境docker配置国内镜像源构建一个Docker 镜像验证镜像合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPant…

MySQL-多表关系、多表查询

一. 一对多(多对一) 1. 例如&#xff1b;一个部门下有多个员工 在数据库表中多的一方(员工表)、添加字段&#xff0c;来关联一的一方(部门表)的主键 二. 外键约束 1.如将部门表的部门直接删除&#xff0c;然而员工表还存在其部门下的员工&#xff0c;出现了数据的不一致问题&am…

【 HarmonyOS 5 入门系列 】鸿蒙HarmonyOS示例项目讲解

【 HarmonyOS 5 入门系列 】鸿蒙HarmonyOS示例项目讲解 一、前言&#xff1a;移动开发声明式 UI 框架的技术变革 在移动操作系统的发展历程中&#xff0c;UI 开发模式经历了从命令式到声明式的重大变革。 根据华为开发者联盟 2024 年数据报告显示&#xff0c;HarmonyOS 设备…

【SSM】SpringMVC学习笔记7:前后端数据传输协议和异常处理

这篇学习笔记是Spring系列笔记的第7篇&#xff0c;该笔记是笔者在学习黑马程序员SSM框架教程课程期间的笔记&#xff0c;供自己和他人参考。 Spring学习笔记目录 笔记1&#xff1a;【SSM】Spring基础&#xff1a; IoC配置学习笔记-CSDN博客 对应黑马课程P1~P20的内容。 笔记2…

借助 Spring AI 和 LM Studio 为业务系统引入本地 AI 能力

Spring AI 1.0.0-SNAPSHOTLM Studio 0.3.16qwen3-4b 参考 Unable to use spring ai with LMStudio using spring-ai openai module Issue #2441 spring-projects/spring-ai GitHub LM Studio 下载安装 LM Studio下载 qwen3-4b 模型。对于 qwen3 系列模型&#xff0c;测试…

C++学习-入门到精通【13】标准库的容器和迭代器

C学习-入门到精通【13】标准库的容器和迭代器 目录 C学习-入门到精通【13】标准库的容器和迭代器一、标准模板库简介1.容器简介2.STL容器总览3.近容器4.STL容器的通用函数5.首类容器的通用typedef6.对容器元素的要求 二、迭代器简介1.使用istream_iterator输入&#xff0c;使用…

Vue Router的核心实现原理深度解析

1. Vue Router的基本架构 Vue Router的核心功能是实现前端路由&#xff0c;即在不重新加载页面的情况下更改应用的视图。它的基本架构包括&#xff1a; 路由配置&#xff1a;定义路径与组件的映射关系路由实例&#xff1a;管理路由状态和提供导航方法路由视图&#xff1a;渲染…

设计模式——状态设计模式(行为型)

摘要 状态设计模式是一种行为型设计模式&#xff0c;核心在于允许对象在内部状态改变时改变行为。它通过状态对象封装不同行为&#xff0c;使状态切换灵活清晰。该模式包含环境类、抽象状态类和具体状态类等角色&#xff0c;具有避免大量分支判断、符合单一职责和开闭原则等特…

C++ 观察者模式:设计与实现详解

一、引言 在现代软件开发中,组件间的交互与通信是系统设计的核心挑战之一。观察者模式(Observer Pattern)作为一种行为设计模式,提供了一种优雅的解决方案,用于实现对象间的一对多依赖关系。本文将深入探讨 C++ 中观察者模式的设计理念、实现方式及其应用场景。 二、观察…

Windows 账号管理与安全指南

Windows 账号管理与安全指南 概述 Windows 账号管理是系统安全的基础&#xff0c;了解如何正确创建、管理和保护用户账户对于系统管理员和安全专业人员至关重要。本文详细介绍 Windows 系统中的账户管理命令、隐藏账户创建方法以及安全防护措施。 基础账户管理命令 net use…

[蓝桥杯]摆动序列

摆动序列 题目描述 如果一个序列的奇数项都比前一项大&#xff0c;偶数项都比前一项小&#xff0c;则称为一个摆动序列。即 a2i<a2i−1,a2i1 >a2ia2i​<a2i−1​,a2i1​ >a2i​。 小明想知道&#xff0c;长度为 mm&#xff0c;每个数都是 1 到 nn 之间的正整数的…

Python 网络编程 -- WebSocket编程

作者主要是为了用python构建实时网络通信程序。 概念性的东西越简单越好理解,因此,下面我从晚上摘抄的概念 我的理解。 什么是网络通信? 更确切地说&#xff0c;网络通信是两台计算机上的两个进程之间的通信。比如&#xff0c;浏览器进程和新浪服务器上的某个Web服务进程在通…

GM DC Monitor如何实现TCP端口状态监控-操作分享

本节讲解如何通过现有指标提取监控脚本制作自定义的TCP端口监控指标 一、功能介绍 通过提取已有的监控指标的监控命令&#xff0c;来自定义TCP端口的监控指标。 二、配置端口监控 1&#xff09;定位监控脚本 确定脚本及参数如下&#xff1a; check_protocol_tcp.pl --plug…

LabVIEW与Modbus/TCP温湿度监控系统

基于LabVIEW 开发平台与 Modbus/TCP 通信协议&#xff0c;设计一套适用于实验室环境的温湿度数据采集监控系统。通过上位机与高精度温湿度采集设备的远程通信&#xff0c;实现多设备温湿度数据的实时采集、存储、分析及报警功能&#xff0c;解决传统人工采集效率低、环境适应性…

Ntfs!ReadIndexBuffer函数分析之nt!CcGetVirtualAddress函数之nt!CcGetVacbMiss

第一部分&#xff1a; NtfsMapStream( IrpContext, Scb, LlBytesFromIndexBlocks( IndexBlock, Scb->ScbType.Index.IndexBlockByteShift ), Scb->ScbType.Index.BytesPerIndexBuffer, &am…

vite+vue3项目中,单个组件中使用 @use报错

报错信息&#xff1a; [plugin:vite:css] [sass] use rules must be written before any other rules.use 官方说明 注意事项&#xff1a; https://sass-lang.com/documentation/at-rules/use/ 样式表中的 use 规则必须位于所有其他规则&#xff08;除 forward 外&#xff0…

基于VMD-LSTM融合方法的F10.7指数预报

F10.7 Daily Forecast Using LSTM Combined With VMD Method ​​F10.7​​ solar radiation flux is a well-known parameter that is closely linked to ​​solar activity​​, serving as a key index for measuring the level of solar activity. In this study, the ​​…

React 新项目

使用git bash 创建一个新项目 建议一开始就创建TS项目 原因在Webpack中改配置麻烦 编译方法:ts compiler 另一种 bable 最好都配置 $ create-react-app cloundmusic --template typescript 早期react项目 yarn 居多 目前npm包管理居多 目前pnpm不通用 icon 在public文件夹中…