【算法专场】哈希表

目录

前言

哈希表

1. 两数之和 - 力扣(LeetCode)

算法分析

算法代码

面试题 01.02. 判定是否互为字符重排

​编辑算法分析

算法代码

217. 存在重复元素

算法分析

算法代码

 219. 存在重复元素 II

算法分析

算法代码

解法二

算法代码

算法分析

算法代码

49. 字母异位词分组

         算法分析

算法代码


前言

当我们想要快速查找某个值是否存在,或者想要对数据进行去重的时候,我们有没有方法可以解决上面这些问题?我们可以用哈希表。

哈希表

哈希表(Hash Table)是一种通过哈希函数将键(key)映射到表中位置来访问记录的数据结构,它具有高效的数据查找、插入和删除能力

我们什么时候可以使用哈希表?

在快速查找、频繁统计、快速映射、去重的情景下都可以使用哈希表。

我们来通过算法题目来更好的了解哈希算法。

1. 两数之和 - 力扣(LeetCode)

算法分析

本道题要求我们从数组中找两个数,并且两数之和为target。这道题可以采用暴力枚举,时间复杂度为O(n^2),如果在大量数据的情况下,是会超时的,那么我们可以采用哈希算法来解决这道题。

我们可以在hash表中存储元素以及其下标的映射。在遍历数组的过程,每次判断(target-当前元素)是否在hash表中存在,如果不存在,那就将

当前元素以及其下标存到hash表中,反之,如果找到,那么就取出下标返回。

为什么不将所有元素都放进去hash表再进行判断?这样的话就无法解决元素重复的问题。假设目标值为2,那么现在有1,我们如果将1先放进了hash表,那么我们在遍历的时候,可以找到1,但实际上这两个1是同一个。而如果我们先判断hash表中是否存在(target-当前元素)的元素,则可以避免出现重复的情况。

算法代码

/*** 解决方案:找出数组中两个数之和等于目标值的数对索引* 方法:使用哈希表实现* 时间复杂度:O(n),其中n是数组的长度* 空间复杂度:O(n),需要额外的空间来存储哈希表* * @param nums 输入的整数数组* @param target 目标值,寻找两数之和等于此值* @return 返回一个长度为2的整数数组,包含满足条件的两个数的索引;如果不存在这样的数对,则返回{-1, -1}*/
public int[] twoSum(int[] nums, int target) {// 利用哈希表来存储已经遍历过的数字及其索引,以便快速检查目标值与当前值的差值是否已经出现过HashMap<Integer,Integer> map=new HashMap<>();for(int i=0;i<nums.length;i++){// 检查当前数字与目标值的差值是否已经在哈希表中if(map.containsKey(target-nums[i])){// 如果差值存在,则找到了满足条件的两个数,返回它们的索引return new int[]{map.get(target-nums[i]),i};}else{// 如果差值不存在,将当前数字及其索引放入哈希表中,以供后续查找使用map.put(nums[i],i);}}// 如果遍历完整个数组后仍未找到满足条件的数对,返回{-1, -1}return new int[]{-1,-1};
}

时间复杂度为O(n),空间复杂度为O(n).

面试题 01.02. 判定是否互为字符重排

算法分析

本道题其实就是要判断两个字符串是否是一样,那么我们就可以两个hash表,来存储每次字符出现的次数,如果两个hash表对应的值都相等,那就说明两个字符串是一样的。

算法代码

    /*** 检查两个字符串是否互为字符重排* * @param s1 第一个字符串* @param s2 第二个字符串* @return 如果两个字符串互为字符重排,则返回true;否则返回false*/public boolean CheckPermutation(String s1, String s2) {// 如果两个字符串长度不同,则它们不可能互为字符重排if (s1.length() != s2.length()) {return false;}// 如果任一字符串为空,则它们不可能互为字符重排if (s1.length() == 0 || s2.length() == 0) {return false;}// 创建一个哈希表来存储字符出现的次数,ASCII码共有128个字符,额外留一个位置给可能的空字符int hash[] = new int[129];// 遍历第一个字符串,统计每个字符出现的次数for (int i = 0; i < s1.length(); i++) {char ch = s1.charAt(i);hash[ch]++;}// 遍历第二个字符串,检查每个字符是否在哈希表中出现过,并减少相应字符的计数for (int i = 0; i < s2.length(); i++) {char ch = s2.charAt(i);// 如果字符在哈希表中的计数为0,则说明两个字符串的字符组成不同if (hash[ch] == 0) {return false;}hash[ch]--;}// 如果所有字符都能一一对应,且没有多余的字符,则两个字符串互为字符重排return true;}

217. 存在重复元素

算法分析

这道题就是要求在数组中有没有一个元素是出现超过两次的,我们可以用哈希算法来解决这道题,利用HashSet,如果set里面没有存在当前元素,就将当前元素存到set中;反之,如果有,则返回true。

算法代码

  public boolean containsDuplicate(int[] nums) {HashSet<Integer> hashSet=new HashSet<>();for(int i=0;i<nums.length;i++){if(hashSet.contains(nums[i])){return true;}hashSet.add(nums[i]);}return false;}

 219. 存在重复元素 II

算法分析

跟上一道题类似,不过这里还需要将下标进行存储,需要利用HashMap,在遍历的过程中,如果当前元素在hashmap中已经存在,那么就判断这两个元素之间的距离,如果小于k,则返回true,否则将当前元素以及其下标存储到hashmap中。 

算法代码

/*** 检查数组中是否存在两个相同的数字,且它们的索引之差的绝对值最大为k* 这个方法通过使用HashMap来跟踪数字及其最后出现的索引来实现* 如果发现重复数字,并且它们的索引之差不超过k,则返回true* 如果不满足这些条件,则在遍历完整个数组后返回false* * @param nums 输入的整数数组* @param k 索引之差的绝对值的最大允许值* @return 如果找到至少一对索引之差的绝对值不超过k的相同数字,则返回true;否则返回false*/public boolean containsNearbyDuplicate2(int[] nums, int k) {// 使用HashMap来存储数字及其对应的索引HashMap<Integer, Integer> map = new HashMap<>();for(int i=0;i<nums.length;i++){// 检查当前数字是否已经在HashMap中存在if(map.containsKey(nums[i])){// 如果当前数字已存在,并且当前索引与之前索引之差不超过k,则返回trueif(i-map.get(nums[i])<=k){return true;}}// 更新或添加当前数字及其索引到HashMap中map.put(nums[i],i);}// 如果没有找到满足条件的数字对,则返回falsereturn false;}

时间复杂度为O(n),空间复杂度为O(n)

解法二

对于这道题,我们还可以通过滑动窗口的思想来解决,题目要求在数组中找两个相同的元素,并且他们下标的距离要小于等于k,那么我们就可以通过维护一个长度为k的窗口。如果当窗口小于k的时候,那么我们就将元素添加到窗口中,如果窗口中存在和当前元素相同的元素,那么就直接返回true,反之,则将元素添加到窗口中,当元素的个数等于窗口的长度的时候,那就将左边第一个元素进行移除。这里我们借助HashSet来判断窗口中是否有重复的元素

算法代码

  /*** 检查数组中是否存在重复的元素,且它们的索引之差的绝对值最大为k* 这个方法用于识别在一定索引范围内是否存在重复的数字** @param nums 一个整数数组,其中可能包含重复元素* @param k 索引之差的绝对值的最大允许值* @return 如果找到至少一对索引之差的绝对值不超过k的重复元素,则返回true;否则返回false*/public boolean containsNearbyDuplicate(int[] nums, int k) {// 使用HashSet存储当前窗口内的元素,以便快速检查重复Set<Integer> set = new HashSet<>();for (int i = 0; i < nums.length; i++) {// 当窗口大小超过k时,移除窗口最左侧的元素,以保持窗口大小不超过kif (i > k) {set.remove(nums[i - k - 1]);}// 尝试将当前元素添加到HashSet中如果添加失败,说明存在重复元素,且索引之差不超过kif (!set.add(nums[i])) {return true;}}// 遍历完成后,如果没有返回true,说明没有找到满足条件的重复元素return false;}

算法分析

这道题相对于前面两道题来说,要难上一些。但是以及依旧可以借鉴上面题目的思想,利用滑动窗口+有序集合

根据题意,假设任意位置为i,值为u。我们希望在下标范围为[max(0,i-k),i)的范围内找到值范围在[u-t,u+t]范围内的数。如果我们每次遍历到任意位置的时候,都往前检查k个元素,这样时间负责度会达到O(nk),会超时,所以我们需要对检索后面k个元素进行优化,在java中,有一个TreeSet数据结构,能够帮助我们在有序集合内快速找到值小于等于u或者大于等于u的值。

算法代码

/*** 检查数组中是否存在两个索引之差不超过indexDiff且值之差不超过valueDiff的元素* * @param nums 包含整数的数组* @param indexDiff 索引之间的最大差值* @param valueDiff 值之间的最大差值* @return 如果找到满足条件的元素对,则返回true;否则返回false*/public boolean containsNearbyAlmostDuplicate(int[] nums, int indexDiff, int valueDiff) {int n = nums.length;TreeSet<Integer> set = new TreeSet<>();for(int i=0;i<n;i++){int u=nums[i];//如果set不为空,从set中找到大于等于u的最小值(最接近u的数)Integer ceil = set.ceiling(u);//如果set不为空,且小于等于u的最大值(最接近u的数)Integer floor = set.floor(u);//检查是否存在满足条件的元素if(ceil!=null&&ceil-u<=valueDiff) return true;if(floor!=null&&u-floor<=valueDiff) return true;//将当前元素加入setset.add(u);//如果当前索引大于等于indexDiff,则从set中移除滑动窗口最左侧的元素if(i>=indexDiff) set.remove(nums[i-indexDiff]);}//遍历后仍未找到满足条件的元素,返回falsereturn false;}

49. 字母异位词分组

 算法分析

这道题要我们找字符串的字符个数都相同的字符串,并将这些字符串都放在同一个列表中,那么我们可以采用哈希算法,这里借助HashMap,键key为字符串,值为一个存储着字符串的列表。在遍历字符串数组的时候,我们每次将字符串进行排序,再判断hashmap是否存储当前字符串,如果存在,则将当前元素添加到列表中,反之,则创建一个列表,并将当前元素添加到列表中。最后再将map中的值存储放到ans中。

算法代码

/*** 对字符串数组进行遍历,将其中的字符串转换为字符数组并排序,然后转换回字符串* 使用HashMap来存储这些转换后的字符串作为键,以及它们在原始数组中的出现情况作为值* 最后,将HashMap中的所有值收集到一个二维列表中并返回* * @param strs 字符串数组,包含待处理的字符串* @return 返回一个二维列表,其中包含按照字母异位词分组的字符串列表*/
public List<List<String>> groupAnagrams(String[] strs) {// 初始化答案列表List<List<String>> ans=new ArrayList<>();// 初始化哈希图,用于存储排序后的字符串作为键,以及它们的出现情况作为值HashMap<String,List<String>> map=new HashMap<>();// 遍历输入的字符串数组for(int i=0;i<strs.length;i++){// 获取当前遍历到的字符串String s=strs[i];// 将字符串转换为字符数组char[] chars=s.toCharArray();// 对字符数组进行排序Arrays.sort(chars);// 将排序后的字符数组转换回字符串s=new String(chars);// 如果排序后的字符串已经在哈希图中存在if(map.containsKey(s)){// 将当前字符串添加到该键对应的列表中map.get(s).add(strs[i]);}else{// 否则,创建一个新的字符串列表List<String> list=new ArrayList<>();// 将当前字符串添加到列表中list.add(strs[i]);// 将排序后的字符串和对应的字符串列表作为键值对存入哈希图map.put(s,list);}}// 遍历哈希图的所有键for(String key:map.keySet()){// 将每个键对应的值(字符串列表)添加到答案列表中ans.add(map.get(key));}// 返回答案列表return ans;
}


以上就是哈希算法篇的所有内容啦~

若有不足,欢迎指正~

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

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

相关文章

PHP本地商家卡券管理系统

本地商家卡券管理系统 —— 引领智慧消费新时代 本地商家卡券管理系统&#xff0c;是基于ThinkPHPUni-appuView尖端技术匠心打造的一款微信小程序&#xff0c;它彻底颠覆了传统优惠方式&#xff0c;开创了多商家联合发行优惠卡、折扣券的全新模式&#xff0c;发卡类型灵活多变…

Kafka分区管理大师指南:扩容、均衡、迁移与限流全解析

#作者&#xff1a;孙德新 文章目录 分区分配操作(kafka-reassign-partitions.sh)1.1 分区扩容、数据均衡、迁移(kafka-reassign-partitions.sh)1.2、修改topic分区partition的副本数&#xff08;扩缩容副本&#xff09;1.3、Partition Reassign场景限流1.4、节点内副本移动到不…

极狐GitLab 17.8 正式发布,多项 DevOps 重点功能解读【二】

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料&#xff1a; 极狐GitLab 官网极狐…

AWTK-WEB 快速入门(4) - JS Http 应用程序

XMLHttpRequest 改变了 Web 应用程序与服务器交换数据的方式&#xff0c;fetch 是 XMLHttpRequest 继任者&#xff0c;具有更简洁的语法和更好的 Promise 集成。本文介绍一下如何使用 JS 语言开发 AWTK-WEB 应用程序&#xff0c;并用 fetch 访问远程数据。 用 AWTK Designer 新…

LabVIEW外腔二极管激光器稳频实验

本项目利用LabVIEW软件开发了一个用于外腔二极管激光器稳频实验的系统。系统能够实现激光器频率的稳定控制和实时监测&#xff0c;为激光实验提供了重要支持。 项目背景&#xff1a; 系统解决了外腔二极管激光器频率不稳定的问题&#xff0c;以满足对激光器频率稳定性要求较高…

计算机毕业设计--基于深度学习技术(Yolov11、v8、v7、v5)算法的高效人脸检测模型设计与实现(含Github代码+Web端在线体验界面)

基于深度学习技术&#xff08;Yolov11、v8、v7、v5&#xff09;算法的高效人脸检测模型 Yolo算法应用之《基于Yolo的花卉识别算法模型设计》&#xff0c;请参考这篇CSDN作品&#x1f447; 计算机毕业设计–基于深度学习技术&#xff08;Yolov11、v8、v7、v5&#xff09;算法的…

国家队出手!DeepSeek上线国家超算互联网平台!

目前,国家超算互联网平台已推出 DeepSeek – R1 模型的 1.5B、7B、8B、14B 版本,后续还会在近期更新 32B、70B 等版本。 DeepSeek太火爆了!在这个春节档,直接成了全民热议的话题。 DeepSeek也毫无悬念地干到了全球增速最快的AI应用。这几天,国内的云计算厂家都在支持Dee…

Android和DLT日志系统

1 Linux Android日志系统 1.1 内核logger机制 drivers/staging/android/logger.c static size_t logger_offset( struct logger_log *log, size_t n) { return n & (log->size - 1); } 写的off存在logger_log中&#xff08;即内核内存buffer&#xff09;&am…

安卓手游内存call综合工具/内部call/安卓注入call/数据分析(类人猿学院)

进程分析注入综合工具总界面 模块分析函数分析遍历 函数分析 so汇编分析 汇编call植入器&#xff0c;支持模拟器x86 x64 和手机arm64指令全平台 防ce搜索数据功能 全国首套发布&#xff0c;阿凡老师学院最好的安卓内存逆向老师&#xff0c;几乎行业最强的&#xff0c;有兴趣可以…

Kotlin 扩展

Kotlin 扩展 引言 Kotlin 作为一种现代编程语言,以其简洁、安全、互操作性强等特点,在 Android 开发领域占据了重要地位。其中,Kotlin 扩展(Extensions)是其一项非常实用的特性,它允许开发者以简洁的方式对类、对象或属性进行扩展。本文将详细介绍 Kotlin 扩展的概念、…

通过例子学 rust 个人精简版 1-1

1-1 Hello World fn main() {println!("Hello World!");// 动手试一试println!("Im a Rustacean!"); }Hello World! Im a Rustacean!要点1 &#xff1a;println 自带换行符 注释 fn main() {let x 5 /* 90 */ 5;println!("Is x 10 or 100? x …

ML.NET库学习007:从SQL数据库中流式读取数据并进行预测分析

文章目录 ML.NET库学习007:从SQL数据库中流式读取数据并进行预测分析项目主要目的和原理项目概述实现的主要功能主要流程步骤使用的主要函数方法关键技术主要功能和步骤功能详细解读实现步骤分步骤代码结构及语法解读使用机器学习进行特征工程:从类别到数值的转换与文本特征提…

闲鱼IP属地是通过电话号码吗?

在闲鱼这样的二手交易平台上&#xff0c;用户的IP属地信息对于维护交易安全、增强用户间的信任至关重要。然而&#xff0c;关于闲鱼IP属地是如何确定的&#xff0c;不少用户存在疑惑&#xff0c;尤其是它与电话号码之间是否存在关联。本文将深入探讨这一问题&#xff0c;揭示闲…

电商小程序(源码+文档+部署+讲解)

引言 随着移动互联网的快速发展&#xff0c;电商小程序成为连接消费者与商家的重要桥梁。电商小程序通过数字化手段&#xff0c;为消费者提供了一个便捷、高效的购物平台&#xff0c;从而提升购物体验和满意度。 系统概述 电商小程序采用前后端分离的架构设计&#xff0c;服…

【20250215】二叉树:94.二叉树的中序遍历

#方法一&#xff1a;递归法 # class Solution: # def inorderTraversal(self,root): # res[] # def dfs(node): # if node is None: # return # #下面代码是不对的&#xff0c;没有体现递归 # #res.a…

Windows环境安装Kafka(集群版)

大家好&#xff0c;最近在准备Java面试&#xff0c;复习到Kafka的相关知识&#xff0c;一时兴起&#xff0c;就想在自己的Windows笔记本上安装一个Kafka集群。下面就记录一下安装步骤。 工具分享 Offset Explorer&#xff1a;Kafka可视化工具 下载地址&#xff1a;https://ww…

完全数和质数算法详解

完全数是指一个正整数&#xff0c;它等于其所有真约数&#xff08;即除了自身以外的所有正因数&#xff09;之和。例如&#xff0c;6 是一个完全数&#xff0c;因为它的真约数是 1、2 和 3&#xff0c;且 1 2 3 6。 1 计算约数和 1.1 遍历 遍历其所有可能的约数并计算它们…

buu-jarvisoj_level2_x64-好久不见37

覆盖缓冲区和 RBP&#xff1a; 使用 128 8 字节覆盖 buf 和 rbp。 构造 ROP 链&#xff1a; pop rdi; ret 地址&#xff1a; 将 pop rdi; ret 指令的地址写入返回地址位置。 /bin/sh 地址&#xff1a; 将 /bin/sh 字符串的地址压入栈顶&#xff0c;作为 system 函数的参数。…

大模型训练为什么依赖GPU

近年来&#xff0c;随着人工智能技术的飞速发展&#xff0c;特别是深度学习领域的进步&#xff0c;大模型的训练逐渐成为研究和工业界的热点。作为大模型训练中的核心硬件&#xff0c;GPU&#xff08;图形处理单元&#xff09;扮演了至关重要的角色。那么&#xff0c;为什么大模…

Python的那些事第二十一篇:Python Web开发的“秘密武器”Flask

基于 Flask 框架的 Python Web 开发研究 摘要 在 Web 开发的江湖里,Python 是一位武林高手,而 Flask 则是它手中那把小巧却锋利的匕首。本文以 Flask 框架为核心,深入探讨了它在 Python Web 开发中的应用。通过幽默风趣的笔触,结合实例和表格,分析了 Flask 的特性、优势以…