当前位置: 首页 > news >正文

优选算法的映射之妙:哈希表专题

专栏:算法的魔法世界

个人主页:手握风云

目录

一、哈希表简介

二、例题讲解

2.1. 两数之和

2.2. 判定是否互为字符重排

2.3. 存在重复元素

2.4. 存在重复元素 II

2.5. 字母异位词分组


一、哈希表简介

  • 哈希表

        哈希表(Hash Table)是一种高效的数据结构,通过 “键 - 值”(Key-Value)对的形式存储和检索数据。

  • 作用

        利用哈希函数将键映射到数组中的特定位置,从而实现快速查找、插入和删除操作。查找、插入、删除操作的时间复杂度均为 O(1),因为哈希函数能直接定位数据位置。

  • 什么时候用哈希表

        当我们需要频繁查找某一个元素的时候,效率非常高。

  • 怎么用哈希表

        在Java的集合框架中基于哈希表实现的HashMap和HashSet。但是新建哈希表和调用接口都是有时间消耗。如果说要处理的数据是字符,或者数据范围比较小的int型时,我们可以使用数据模拟哈希表。比如字符,我们可以利用ASCII码值映射到数组的下标。

二、例题讲解

2.1. 两数之和

        给定一个整数数组 nums 和一个整数目标值 target,在数组中找到和等于 target 的两个不同元素,返回这两个元素的数组下标

        这个题的暴力枚举思想很简单,先固定其中一个数,然后依次与前面的数字进行相加,这样能做到不重不漏。时间复杂度O(n^{2})

class Solution {public int[] twoSum(int[] nums, int target) {for (int i = nums.length - 1; i >= 0; i--) {for (int j = i - 1; j >= 0; j--) {if (nums[i] + nums[j] == target) {return new int[]{i ,j};}}}return new int[0];}
}

        接下来使用哈希表进行优化:当我们固定nums[i]的时候,我们需要在前面寻找target - nums[i],那我们就可以先遍历数组,把数组元素丢进哈希表,再让指针向后移动,如果能找到target - nums[i],就直接返回下标,没找到就继续向后移动。我们还需要判断一种情况,就是如果x == target - nums[i],就会自己找到自己。

        完整代码实现:

class Solution {public int[] twoSum(int[] nums, int target) {Map<Integer,Integer> hash = new HashMap<>();for (int i = 0; i < nums.length; i++) {int x = target - nums[i];if (hash.containsKey(x)) {return new int[]{i, hash.get(x)};}hash.put(nums[i],i);}return new int[]{-1, -1};}
}

2.2. 判定是否互为字符重排

        判断其中一个字符串通过字符重新排列后,能否完全变成另一个字符串(即两字符串本质是 “字符组成与个数完全相同,仅顺序不同”)。

        如果两个字符串长度不相等,直接返回false。我们可以先枚举出s1所有的重排结果,再与s2进行比较,但这样的时间复杂度会达到指数级别。此时我们就可以利用哈希表来统计每个字符出现的次数,比较两个哈希表中每个字符出现的次数是否相同。这时我们就可以借助字符的ASCII码值,利用数组模拟哈希表。在此基础上,我们还可以优化,只利用一个哈希表就行:先遍历字符串s1,将s1中的字符丢进哈希表,再去遍历s2,出现的字符则减少,如果hash[s2.charAt(i) - 'a'] < 0,返回false。

class Solution {public boolean CheckPermutation(String s1, String s2) {if (s1.length() != s2.length()) {return false;}int[] hash = new int[26];// 统计s1中每个字符出现的次数for (int i = 0; i < s1.length(); i++) {hash[s1.charAt(i) - 'a']++;}for (int i = 0; i < s2.length(); i++) {hash[s2.charAt(i) - 'a']--;if (hash[s2.charAt(i) - 'a'] < 0) {return false;}}return true;}
}

2.3. 存在重复元素

        判断数组中是否存在重复元素。

        创建一个哈希表,遍历数组,如果哈希表中存在该元素,返回true;没有,则丢进哈希表。

        完整代码实现:

class Solution {public boolean containsDuplicate(int[] nums) {Set<Integer> set = new HashSet<>();for (int i : nums) {if (set.contains(i)) {return true;}set.add(i);}return false;}
}

2.4. 存在重复元素 II

        与上一题不同的是,找出相等元素,索引距离不超过 k。

        遍历数组,如果哈希表中不存在该元素,则将它本身和下标一起丢进哈希表中,如果存在,在判断索引距离是否<=k。如果后面还存在重复元素,我们可以直接覆盖,因为我们要找的是距离最近的重复元素。

        完整代码实现:

class Solution {public boolean containsNearbyDuplicate(int[] nums, int k) {Map<Integer, Integer> map = new HashMap<Integer, Integer>();int length = nums.length;for (int i = 0; i < length; i++) {int num = nums[i];if (map.containsKey(num) && i - map.get(num) <= k) {return true;}map.put(num, i);}return false;}
}

2.5. 字母异位词分组

        给定一个字符串数组,需将其中的字母异位词(字母种类、数量完全相同,仅排列顺序不同的字符串)归为一组,最终返回包含所有分组的列表。

        我们需要先判断这些单词是否为字母异位词,我们这里可以我们利用字符的ASCII码值进行排序。对于字符串的分组,我们可以将哈希表的键值对类型定义为HashMap<String, List<String>>,遍历完一个字符串,符合要求,直接丢进新创建的顺序表中。

        完整代码实现:

class Solution {public List<List<String>> groupAnagrams(String[] strs) {Map<String, List<String>> hash = new HashMap<>();for (String s : strs) {char[] tmp = s.toCharArray();// 对字符数组进行排序,这样字母异位词就会变成相同的字符串Arrays.sort(tmp);String key = new String(tmp);if (!hash.containsKey(key)) {// 将字符串添加到对应分组hash.put(key, new ArrayList<>());}hash.get(key).add(s);}return new ArrayList<>(hash.values());}
}
http://www.dtcms.com/a/362482.html

相关文章:

  • 固定资产管理系统核心功能拆解:批量导入、OCR 识别有多高效?
  • Linux内核O(1)调度算法
  • 云计算学习笔记——Linux系统网络配置与远程管理(ssh)篇
  • 二进制流进行预览pdf、excel、docx
  • 手把手教你学 Simulink (1.3):探索Simulink模块库的奇妙世界
  • QT6(QFileSystemModel和QTreeView)
  • 第三方软件测评:第三方组件(如 jQuery、Bootstrap)的 WEB安全测试方法
  • Element Plus 表格表单校验功能详解
  • 封装Element UI中el-table表格为可配置列公用组件
  • ubantu20.04 git clone 无法连接问题与解决方法
  • Hard Disk Sentinel:全面监控硬盘和SSD的健康与性能
  • SQLSERVER基本cmd操作命令
  • 2025含金量高的市场岗位证书有哪些?
  • 4种有效方法将联想手机数据传输到电脑
  • 设计软件启动失败?“找不到vcruntime140.dll,无法继续执行代码” 场景化解决方案来了
  • 【Stream API】高效简化集合处理
  • 智能数据采集实战:从爬取到分析一步到位
  • 【音视频】VP8 与 VP9 技术详解及与 H.264 H.265 的对比
  • FFmpeg命令行音视频工具:高效实现格式转换与批量处理,支持音频提取与精准视频剪辑
  • 【LeetCode牛客数据结构】单链表的应用——环形链表及链表分割问题详解
  • 【音视频】WebRTC-NACK
  • 苹果手机文本转音频,自行制作背诵素材
  • CentOS 创建站点
  • 从零开始学习C#上位机开发学习进阶路线,窥探工业自动化和物联网应用
  • Windows---DWORD与IPVOID
  • milvus-standalone启动失败unhealthy,错误日志context deadline exceeded
  • 2023知识图谱与大模型融合实践研究报告
  • Centos10虚拟机安装Zabbix
  • ELK 统一日志分析系统部署与实践指南(下)
  • cv610单独烧录 ddr失败