【算法专题训练】19、哈希表

1、哈希表基础知识

  • 以键值对的方式进行数据存储
  • 优点:哈希表数据结构在插入、删除或查找一个元素时,都只需要O(1)的时间

哈希表设计三要点:

  • 为了快速确定一个元素在哈希表中的位置,可以使用一个数组,元素的位置为他的哈希值除于数组长度的余数。
  • 由于多个哈希值不同的元素可能会被存入同一数组位置,数组的每个位置对应一个链表,因此存入同一位置的多个元素都被添加到同一个链表中。
  • 为了确保链表不会太长,就需要计算哈希表中元素的数目与数组长度的比值。当这个比值超过某个阈值时,就对数组进行扩容处理,并把哈希表中的所有元素重新分配位置。

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

题目信息:

  • https://leetcode.cn/problems/FortPu/description/
设计一个支持在平均 时间复杂度 O(1) 下,执行以下操作的数据结构:insert(val):当元素 val 不存在时返回 true ,并向集合中插入该项,否则返回 falseremove(val):当元素 val 存在时返回 true ,并从集合中移除该项,否则返回 false 。
getRandom:随机返回现有集合中的一项。每个元素应该有 相同的概率 被返回。示例 1:
输入: inputs = ["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"]
[[], [1], [2], [2], [], [1], [2], []]
输出: [null, true, false, true, 2, true, false, 2]
解释:
RandomizedSet randomSet = new RandomizedSet();  // 初始化一个空的集合
randomSet.insert(1); // 向集合中插入 1 , 返回 true 表示 1 被成功地插入
randomSet.remove(2); // 返回 false,表示集合中不存在 2
randomSet.insert(2); // 向集合中插入 2 返回 true ,集合现在包含 [1,2]
randomSet.getRandom(); // getRandom 应随机返回 1 或 2
randomSet.remove(1); // 从集合中移除 1 返回 true 。集合现在包含 [2]
randomSet.insert(2); // 2 已在集合中,所以返回 false
randomSet.getRandom(); // 由于 2 是集合中唯一的数字,getRandom 总是返回 2提示:
-231 <= val <= 231 - 1
最多进行 2 * 105 次 insert , remove 和 getRandom 方法调用
当调用 getRandom 方法时,集合中至少有一个元素

解题思路:

  • 1、审题:实现时间复杂度O(1)的哈希表,包含操作插入,删除,和随机获取内部数据
  • 2、解题:该题要实现哈希表的功能,主要要求是时间复杂度为O(1)
  • 插入操作:
    • 使用动态数组vector保存插入后的数据,这样可以随机访问数组内的元素
  • 删除操作:
    • 要实现数据的删除,需要先知道该数值在数组内的下标位置,可以使用map数据结构保存,key为数值,value为该数值在数组中的下标位置
    • 这样就可以通过数值获取到对应保存的下标位置,
    • 还有一个问题是数组中元素删除,需要将后面部分元素进行整体移动,时间复杂度为O(n)
    • 要实现数组元素删除时间复杂度为O(1),可将当前需要删除的元素与数组尾部元素进行交换,然后直接删除数组尾部的元素
  • 随机获取操作:
    • 使用random随机获取数组内的某一个元素

代码实现:

class RandomizedSet
{
public:RandomizedSet(){}bool insert(int val){if (arrLocationMap.find(val) != arrLocationMap.end()) // 已经包含了{return false;}// 加入到数组和哈希表中arrLocationMap[val] = array.size();array.push_back(val);return true;}bool remove(int val){// 先判断数组中是否包含该数值if (arrLocationMap.find(val) == arrLocationMap.end()) // 不包含{return false;}// print();// 找到要删除原始的下标位置int removeIndex = arrLocationMap[val];// 与数组最后元素交换int size = array.size();int removeVal = array[removeIndex];int tailVal = array[size - 1];arrLocationMap[tailVal] = removeIndex;array[removeIndex] = tailVal;array[size - 1] = removeVal;// 删除数组最后一个元素array.pop_back();arrLocationMap.erase(val);return true;}/** Get a random element from the set. */int getRandom(){// 使用mt引擎std::mt19937 generate(rd());// 创建分布std::uniform_int_distribution<int> dist(0, array.size() - 1);int index = dist(generate);return array[index];}private:std::vector<int> array;std::map<int, int> arrLocationMap; // 保存数组元素,和对应的数组下标std::random_device rd;             // 初始化随机数生成数
};

3、总结

  • 普通的map哈希表结构为数组与链表组合,插入与获取数据操作,需要遍历链表,时间复杂度为O(n)
  • 要设计O(1)时间复杂度的哈希表,可使用数组进行插入与获取数据,时间复杂度为O(1),因为数组可通过下标索引操作
  • 而数组的删除操作,可利用交换处理,转变为最终删除数组尾部元素,只是要知道删元素的位置所在,所以需要一个map值保存每个元素在数组中的下标位置。
  • map操作方法,find为查询元素是否存在,erase为删除元素操作。

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

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

相关文章

某光伏电力监控系统网络安全监测项目:智能组网技术优化方案实践

背景与挑战随着光伏电力行业的快速发展&#xff0c;光伏电站的规模和分布范围日益扩大。电力监控系统作为光伏电站的核心平台&#xff0c;其网络安全直接关系到电力生产的稳定性与可靠性。然而&#xff0c;光伏场站通常分布在偏远地区&#xff0c;网络环境复杂&#xff0c;传统…

GEE训练教程:基于Landsat 8卫星影像识别并提取指定区域内无云覆盖的区域多边形,最终导出为矢量文件

简介 本文使用Google Earth Engine平台,通过Landsat 8卫星影像识别并提取指定区域内无云覆盖的区域多边形,最终导出为矢量文件。主要步骤包括:定义研究区域、创建云检测算法、筛选高质量影像、将无云区域转换为矢量多边形,并进行可视化检查和数据导出。 使用Google Earth…

UniApp 页面通讯方案全解析:从 API 到状态管理的最佳实践

在 UniApp 跨端开发中&#xff0c;组件与页面间的通讯是核心需求。无论是父子组件交互、跨页面数据传递&#xff0c;还是全局状态共享&#xff0c;选择合适的通讯方案直接影响代码的可维护性和性能。本文将系统对比 uni.$emit 系列 API、状态管理库&#xff08;Vuex/Pinia&…

【c++进阶系列】:万字详解AVL树(附源码实现)

&#x1f525; 本文专栏&#xff1a;c &#x1f338;作者主页&#xff1a;努力努力再努力wz &#x1f4aa; 今日博客励志语录&#xff1a; 路在脚下延伸时&#xff0c;不必追问终点何在。你迈出的每一步&#xff0c;都在重新定义世界的边界 ★★★ 本文前置知识&#xff1a; …

前端日志回捞系统的性能优化实践|得物技术

一、前言在现代前端应用中&#xff0c;日志回捞系统是排查线上问题的重要工具。然而&#xff0c;传统的日志系统往往面临着包体积过大、存储无限膨胀、性能影响用户体验等问题。本文将深入分析我们在dw/log和dw/log-upload两个库中实施的关键性能优化&#xff0c;以及改造过程中…

【QT随笔】结合应用案例一文完美概括QT中的队列(Queue)

【QT随笔】结合应用案例一文完美概括QT中的队列&#xff08;Queue&#xff09; 队列&#xff08;Queue&#xff09;是一种线性数据结构&#xff0c;其核心规则为先进先出&#xff08;FIFO, First-In-First-Out&#xff09;&#xff1a; 新元素在队尾插入&#xff08;enqueue&a…

At least one <template> or <script> is required in a single file component

环境rspack vue3原因rule 中配置了两个vue-loader删掉一个即可。

LangChain实战(十八):构建ReAct模式的网页内容摘要与分析Agent

本文是《LangChain实战课》系列的第十八篇,将深入讲解如何构建一个基于ReAct模式的智能网页内容摘要与分析Agent。这个Agent能够自主浏览网页、提取关键信息、生成智能摘要,并进行深入的内容分析,让信息获取和理解变得更加高效。 前言 在信息爆炸的时代,我们每天都需要处理…

debian11 ubuntu24 armbian24 apt install pure-ftpd被动模式的正确配置方法

debian11 ubuntu24 armbian24 apt install pure-ftpd被动模式的正确配置方法 安装方法请看&#xff1a;https://www.itbulu.com/pure-ftpd.html 疑难问题解决 原本以为配置很简单的&#xff0c;无非是修改 ForcePassiveIP MinUID PassivePortRange PureDB这几个配置项就行了…

量化金融|基于算法和模型的预测研究综述

一、研究背景与发展历程​​1.​​量化投资理论演进​​•奠基阶段&#xff08;1950s-1960s&#xff09;​​&#xff1a;Markowitz均值方差理论&#xff08;1952&#xff09;、CAPM模型&#xff08;1964&#xff09;奠定现代量化投资基础•衍生品定价&#xff08;1970s-1980s&…

从零开始的云计算生活——第六十天,志在千里,使用Jenkins部署K8S

一.安装kubectl1、配置yum源cat <<EOF | tee /etc/yum.repos.d/kubernetes.repo [kubernetes] nameKubernetes baseurlhttps://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/rpm/ enabled1 gpgcheck1 gpgkeyhttps://mirrors.aliyun.com/kubernetes-new/core/sta…

无人机电压模块技术剖析

无人机电源模块的基本运行方式无人机电压模块的核心任务是对动力电源&#xff08;通常是锂电池&#xff09;进行转换、调节和分配&#xff0c;为飞控、图传、摄像头、舵机等各个子系统提供稳定可靠的电能。其运行方式可以概括为&#xff1a;电压转换与调控&#xff1a;无人机动…

MATLAB基于GM(灰色模型)与LSTM(长短期记忆网络)的组合预测方法

一、GM与LSTM的基本原理及互补性 1. GM模型的核心特点基本原理&#xff1a;通过累加生成&#xff08;AGO&#xff09;将原始无序序列转化为具有指数规律的光滑序列&#xff0c;建立一阶微分方程&#xff08;如GM(1,1)&#xff09;进行预测。其数学形式为&#xff1a; dx(1)dtax…

【菜狗每日记录】启发式算法、傅里叶变换、AC-DTC、Xmeans—20250909

&#x1f431;1、启发式算法 ① 定义 ② 特点 ③ 案例 &#x1f431;2、快速傅里叶变换FFT ① DFT离散傅里叶变换 ② FFT快速傅里叶变换 &#x1f431;3、AC-DTC聚类 &#x1f431;4、Xmeans &#x1f431;1、启发式算法 启发式算法是和最优化算法相对的。 一般而言&am…

Axure移动端选择器案例:多类型选择器设计与动态效果实现

在移动端交互设计中&#xff0c;选择器是用户输入的核心组件。Axure移动端高保真元件库提供了四种关键选择器解决方案&#xff0c;通过动态效果提升操作真实感&#xff1a; 预览地址&#xff1a;Axure 1. 基础选择器 采用底部弹窗设计&#xff0c;支持单选项快速选择。点击触发…

Spring Boot图片验证码功能实现详解 - 从零开始到完美运行

Spring Boot图片验证码功能实现详解 - 从零开始到完美运行 &#x1f4d6; 前言 大家好&#xff01;今天我要和大家分享一个非常实用的功能&#xff1a;Spring Boot图片验证码。这个功能可以防止恶意攻击&#xff0c;比如暴力破解、刷票等。我们实现的是一个带有加减法运算的图片…

HarmonyOS实现快递APP自动识别地址

​ 大家好&#xff0c;我是潘Sir&#xff0c;持续分享IT技术&#xff0c;帮你少走弯路。《鸿蒙应用开发从入门到项目实战》系列文章持续更新中&#xff0c;欢迎关注&#xff01; 随着鸿蒙&#xff08;HarmonyOS&#xff09;生态发展&#xff0c;越来越多的APP需要进行鸿蒙适…

CUDA编程13 - 测量每个Block的执行时间

一:概述 GPU 程序性能不是靠 CPU 那样的“顺序执行”来衡量的,而是靠线程块(block)和多处理器(SM)利用率。每个 block 在 GPU 的不同多处理器上执行,顺序不确定。传统的 kernel 总体计时(比如 cudaEvent 计时整个 kernel)只能知道总时间,无法分析哪个 block 慢,为什…

敏捷开发-Scrum(下)

Scrum 核心构成&#xff1a;团队、事件与工件的协同价值体系 在 Scrum 框架中&#xff0c;“团队、事件、工件” 并非孤立的模块&#xff0c;而是相互咬合的有机整体&#xff1a;Scrum 团队是价值交付的执行核心&#xff0c;Scrum 事件是节奏把控与反馈调整的机制载体&#xff…

LeetCode 单调栈 739. 每日温度

739. 每日温度给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0c;请在该位置用 0 来代替。 示例 1: 输入…