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

我爱学算法之—— 哈希

哈希表高频算法题解析与实现(C++)

哈希表作为一种高效的数据结构,能以近似 O (1) 的时间复杂度实现查找、插入和删除操作,在解决 “两数之和”“重复元素判断”“字符异位词分组” 等经典算法问题中具有显著优势。

一、两数之和

题目解析

在这里插入图片描述

给定一个整数数组nums和一个目标值target,要求在数组中找到和为target的两个整数,最终返回这两个整数的下标。核心约束:数组中每个元素只能使用一次,且保证有且仅有一个有效答案。

算法思路

暴力解法

通过双重循环枚举所有可能的二元组,判断其和是否等于target

  • 外层循环遍历数组每个元素(下标i),内层循环遍历i之前的所有元素(下标jj < i);
  • nums[i] + nums[j] == target,直接返回[j, i](需注意下标顺序)。
  • 时间复杂度:O (n²)(双重循环),空间复杂度:O (1)(无额外空间消耗)。

哈希表优化

利用哈希表存储 “已遍历元素的值 - 下标” 映射,将内层循环的 O (n) 查找优化为 O (1):

  • 遍历数组时,对当前元素nums[i],计算其 “互补值”x = target - nums[i]
  • 检查哈希表中是否存在x:若存在,直接返回[哈希表中x的下标, i];若不存在,将当前元素nums[i]及其下标i存入哈希表;
  • 仅需遍历一次数组,且无需处理 “元素重复” 问题(因题目保证仅有一个答案,且互补值必在已遍历元素中)。
  • 时间复杂度:O (n),空间复杂度:O (n)(哈希表存储最多 n 个元素)。

代码实现

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {int n = nums.size();vector<int> ret(2);unordered_map<int, int> hash;for (int i = 0; i < n; i++) {int x = target - nums[i];if (hash.find(x) != hash.end()) {ret[0] = i;ret[1] = hash[x];break;}hash[nums[i]] = i;}return ret;}
};

二、判定是否互为字符重排

题目解析

在这里插入图片描述

给定两个仅由小写字母组成的字符串s1s2,判断二者是否为字符重排(即两个字符串包含的字符种类和每种字符的数量完全相同,仅排列顺序可能不同)。例如:s1 = "abc"s2 = "cba"是字符重排;s1 = "aab"s2 = "abb"不是字符重排。

算法思路

字符重排的核心是 “字符种类和数量一致”,因此可通过计数哈希实现:

  1. 由于字符串仅包含 26 个小写字母,可使用大小为 26 的数组(替代哈希表)存储每种字符的出现次数,数组下标对应字母('a'对应 0,'b'对应 1,…,'z'对应 25);
  2. 遍历s1,统计每种字符的出现次数,存入数组count1
  3. 遍历s2,统计每种字符的出现次数,存入数组count2
  4. 对比count1count2:若所有位置的计数均相等,则为字符重排;否则不是。
  • 时间复杂度:O (n)(n 为两个字符串的最大长度),空间复杂度:O (1)(仅使用固定大小的数组)。

代码实现

class Solution {
public:int hash1[30];int hash2[30];bool CheckPermutation(string s1, string s2) {for (auto& e : s1)hash1[e - 'a']++;for (auto& e : s2)hash2[e - 'a']++;for (int i = 0; i < 26; i++) {if (hash1[i] != hash2[i])return false;}return true;}
};

三、存在重复元素

题目解析

在这里插入图片描述

算法思路

这个算法的思路其实很简单,就是用哈希集合来帮我们查有没有重复的数。

具体来说,就是逐个看数组里的每个数:

  • 每拿到一个数,先去哈希集合里找找看有没有这个数
  • 如果找到了,那就说明之前已经出现过这个数了,直接返回 true
  • 如果没找到,就把这个数放进哈希集合里,再看下一个数
  • 等把所有数都看完了还没发现重复的,那就返回 false

代码实现

class Solution {
public:bool containsDuplicate(vector<int>& nums) {unordered_set<int> hash;for (auto& e : nums) {if (hash.find(e) != hash.end())return true;hash.insert(e);}return false;}
};

四、存在重复元素 II

题目解析

在这里插入图片描述

给定一个整数数组nums和一个整数k,判断数组中是否存在两个相等的元素,且它们的下标之差的绝对值不超过k(即abs(i - j) <= k,其中nums[i] == nums[j]i != j)。例如:nums = [1,2,3,1]k = 3返回true(下标 0 和 3 的差为 3,满足 <=3);nums = [1,0,1,1]k = 1返回true

算法思路

这个算法的思路挺好懂的,就是用一个哈希表(map)来记每个数字最后一次出现的位置,然后边遍历数组边检查:

  1. 遍历数组里的每个元素,记下当前元素的下标 i
  2. 对每个元素 nums [i],先看看哈希表里有没有它:
    • 如果有,就算算现在的下标 i 和哈希表里记录的那个下标差多少
    • 要是这个差值小于等于 k,那就说明找到符合条件的两个重复元素了,直接返回 true
  3. 不管哈希表里有没有这个元素,最后都把当前元素和它的下标 i 存进哈希表(这样能保证表里存的总是这个元素最近出现的位置)
  4. 等把所有元素都看完了还没找到符合条件的,就返回 false

代码实现

class Solution {
public:bool containsNearbyDuplicate(vector<int>& nums, int k) {map<int, int> hash;int n = nums.size();for (int i = 0; i < n; i++) {if ((hash.count(nums[i]) != 0) && (i - hash[nums[i]] <= k)) {return true;}hash[nums[i]] = i;}return false;}
};

五、字母异位词分组

题目解析

在这里插入图片描述

给定一个字符串数组strs,将其中所有字母异位词分组(字母异位词定义同 “字符重排”,即字符种类和数量相同,排列顺序不同),最终返回分组后的二维数组。

算法思路

这道题我们可以将 排序后的字符串 作为key值,将字符串数组作为value

  1. 对于数组里的每个字符串,先做一个副本并对副本进行排序
    • 比如 “eat” 排序后是 “aet”,“tea” 排序后也是 “aet”,这样异位词就会有相同的排序结果
  2. 用一个哈希表(unordered_map)来存分组:
    • 表的 key 就是排序后的字符串(比如 “aet”)
    • 表的 value 是一个数组,专门存所有排序后等于这个 key 的原字符串(比如 [“eat”,“tea”,“ate”])
  3. 遍历完所有字符串后,哈希表里每个 value 就是一组字母异位词
  4. 最后把这些 value 收集起来,就是要返回的分组结果

代码实现

class Solution {
public:vector<vector<string>> groupAnagrams(vector<string>& strs) {unordered_map<string, vector<string>> hash;for (auto& e : strs) {string tmp = e;sort(tmp.begin(), tmp.end());hash[tmp].push_back(e);}// 构建结果vector<vector<string>> ret;for (auto& e : hash) {ret.push_back(e.second);}return ret;}
};

本篇文章到这里就结束了,感谢支持
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws

http://www.dtcms.com/a/617793.html

相关文章:

  • Linux字符设备驱动模型
  • C++ List 容器详解:迭代器失效、排序与高效操作
  • 婚纱网站wordpress微商模板
  • GPT问答:泛型、哈希表与缓存、命名参数。251116
  • 免费学软件的自学网站保健品网站建设流程
  • 网络访问流程:HTTPS + TCP + IP
  • 智能体AI、技术浪潮与冲浪哲学
  • 基于 PyTorch + BERT 意图识别与模型微调
  • 沃尔沃公司网站建设微信官方网站建设
  • 网站备案域名怎么买找在农村适合的代加工
  • 42 解决一些问题
  • Claude Code 功能+技巧
  • 基于人脸识别和 MySQL 的考勤管理系统实现
  • AUTOSAR_CP_OS-Operating System for Multi-Core:多核操作系统
  • 什么是 “信任模型” 和 “安全假设”?
  • 【秣厉科技】LabVIEW工具包——HIKRobot(海康机器人系列)
  • 网易UU远程全功能技术解构:游戏级性能突围与安全边界探析
  • 蓝桥杯第八届省赛单片机设计完全入门(零基础保姆级教程)
  • 搭建网站分类建立名词
  • 没有域名的网站wordpress占用资源
  • RPA+AI双剑合璧!小红书商品笔记自动发布,效率提升2000%[特殊字符]
  • 19.传输层协议UDP
  • linux服务-rsync+inotify文件同步-rsync
  • 机器学习之ravel()的作用
  • Wi-Fi 7路由器性能分析:从传输速率到多设备协同全面解析
  • 【Java手搓RAGFlow】-1- 环境准备
  • 审计部绩效考核关键指标与综合评估方法
  • Photoshop - Photoshop 工具栏(29)钢笔工具
  • 营销型网站策划方案大德通众包做网站怎么样
  • 使用 Web Workers 提升前端性能:让 JavaScript 不再阻塞 UI