算法沉淀——哈希算法(leetcode真题剖析)
算法沉淀——哈希算法
- 01.两数之和
- 02.判定是否互为字符重排
- 03.存在重复元素
- 04.存在重复元素 II
- 05.字母异位词分组
哈希算法(Hash Algorithm)是一种将任意长度的输入(也称为消息)映射为固定长度的输出的算法。这个输出通常称为哈希值或摘要。哈希算法的主要目的是快速、高效地检索数据,因为哈希值可以用作数据的唯一标识。
哈希算法的特点包括:
- 固定输出长度: 无论输入的数据大小如何,哈希算法都会生成固定长度的哈希值。
- 快速计算: 对于给定的输入,哈希算法应该迅速生成相应的哈希值。
- 不可逆性: 从哈希值不能逆向推导出原始输入的内容。即使输入的数据发生微小变化,生成的哈希值也应该是大不相同的。
- 雪崩效应: 输入数据的微小变化应该导致输出哈希值的巨大变化,以确保输入数据的任何改变都能产生不同的哈希值。
在算法题中,哈希算法有许多实际运用。以下是一些常见的应用场景:
- 查找和检索: 使用哈希表(HashMap)来快速查找元素。通过将元素的键映射到哈希表中的索引,可以在常量时间内执行查找操作。
- 去重: 利用哈希集合(HashSet)来检测和删除重复元素。通过将元素的哈希值映射到集合中,可以轻松检测是否已经存在相同的元素。
- 缓存: 使用哈希表来实现缓存,以快速检索先前计算的结果。这种方法被称为缓存哈希。
- 字符串匹配: 使用哈希算法来加速字符串匹配过程。例如,Rabin-Karp字符串匹配算法使用哈希值来比较字符串,以快速检测是否匹配。
- 数据校验: 哈希算法用于验证数据的完整性。通过生成数据的哈希值并将其与已知的哈希值进行比较,可以确保数据在传输或存储过程中没有被篡改。
- 分布式系统: 在分布式系统中,哈希算法被用于负载均衡和数据分片。通过将资源或数据的标识哈希到一组节点上,可以实现均匀分布和高效的访问。
- 密码学: 在密码学中,哈希算法用于生成密码的摘要,以便安全地存储密码或验证用户身份。
- 图算法: 在图算法中,哈希算法可用于快速判断两个图是否相同或是否存在同构关系。
01.两数之和
题目链接:https://leetcode.cn/problems/two-sum/
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
- 只会存在一个有效答案
**进阶:**你可以想出一个时间复杂度小于 O(n2)
的算法吗?
思路
如果我们在事先将「数组内的元素」和「下标」绑定在一起存入「哈希表」中,然后直接在哈希表中查找每一个元素的 target - nums[i],就能快速地找到「目标和的下标」。这里有一个小技巧,我们可以不用将元素全部放入到哈希表之后再来二次遍历(因为要处理元素相同的情况)。而是在将元素放入到哈希表中的「同时」,直接来检查表中是否已经存在当前元素所对应的目标元素(即 target - nums[i])。如果它存在,那么我们已经找到了对应解,并立即将其返回。无需将元素全部放入哈希表中,提高效率。由于哈希表中查找元素的时间复杂度是 O(1),遍历一遍数组的时间复杂度为 O(N),因此可以将时间复杂度降到 O(N)。这是一个典型的「用空间换时间」的方式。
代码
class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {// 哈希表,用于存储元素值及其对应的索引unordered_map<int, int> hash;int n = nums.size();for(int i = 0; i < n; ++i) {int x = target - nums[i]; // 计算目标值与当前元素的差值if(hash.count(x)) {// 如果差值在哈希表中存在,说明找到了两个数的和等于目标值return {hash[x], i};}hash[nums[i]] = i; // 将当前元素值及其索引存入哈希表}// 如果未找到符合条件的两个数,返回 {-1, -1}return {-1, -1};}
};
02.判定是否互为字符重排
题目链接:https://leetcode.cn/problems/check-permutation-lcci/
给定两个由小写字母组成的字符串 s1
和 s2
,请编写一个程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。
示例 1:
输入: s1 = "abc", s2 = "bca"
输出: true
示例 2:
输入: s1 = "abc", s2 = "bad"
输出: false
说明:
0 <= len(s1) <= 100
0 <= len(s2) <= 100
思路
这里使用哈希的思想,首先我们可以将两个字符串分别建立哈希,然后再进行对比,但这样时间和空间复杂度都很高,所以我们第一次优化使用一个哈希遍历完第一个字符串,再将第二个字符串进行遍历,每次减计数前先判断是否计数已经为0,如果已经为0,说明不匹配,直接返回false
,这里要提一点,因为这里是26个小写字母,所以我们可以直接使用数组来进一步优化,其次,字符串如果长度不相等我们可以在最开始就判断为false
代码
class Solution {
public:bool CheckPermutation(string s1, string s2) {// 如果两个字符串长度不相等,直接返回 falseif(s1.size() != s2.size()) return false;int hash[26] = {0}; // 用于统计每个字符在 s1 中的出现次数// 统计 s1 中每个字符的出现次数for(char& c : s1) {hash[c - 'a']++;}// 遍历 s2 中的字符for(char& c : s2) {// 如果字符 c 在 s1 中不存在或出现次数已经用尽,返回 falseif(hash[c - 'a'] == 0) {return false;}hash[c - 'a']--; // 减少字符 c 在 s1 中的出现次数}// 如果遍历完 s2 后每个字符在 s1 中的出现次数都匹配,返回 truereturn true;}
};
03.存在重复元素
题目链接:https://leetcode.cn/problems/contains-duplicate/
给你一个整数数组 nums
。如果任一值在数组中出现 至少两次 ,返回 true
;如果数组中每个元素互不相同,返回 false
。
示例 1:
输入:nums = [1,2,3,1]
输出:true
示例 2:
输入:nums = [1,2,3,4]
输出:false
示例 3:
输入:nums = [1,1,1,3,3,4,3,2,4,2]
输出:true
提示:
1 <= nums.length <= 105
-109 <= nums[i] <= 109
思路
这里我们使用哈希中的set
容器就可以很好的解决这个问题,我们将数组中的数一个一个插入set,再插入之前先统计该数是否已经存在,存在就返回true
,全部插入完毕,说明不存在重复元素。
代码
class Solution {
public:bool containsDuplicate(vector<int>& nums) {unordered_set<int> hash; // 用于存储已经遍历过的元素// 遍历数组中的每个元素for(int& i : nums) {// 如果当前元素已经在 hash 中存在,说明数组包含重复元素,返回 trueif(hash.count(i)) {return true;}// 将当前元素插入到 hash 中hash.insert(i);}// 如果遍历完数组都没有发现重复元素,返回 falsereturn false;}
};
04.存在重复元素 II
题目链接:https://leetcode.cn/problems/contains-duplicate-ii/
给你一个整数数组 nums
和一个整数 k
,判断数组中是否存在两个 不同的索引 i
和 j
,满足 nums[i] == nums[j]
且 abs(i - j) <= k
。如果存在,返回 true
;否则,返回 false
。
示例 1:
输入:nums = [1,2,3,1], k = 3
输出:true
示例 2:
输入:nums = [1,0,1,1], k = 1
输出:true
示例 3:
输入:nums = [1,2,3,1,2,3], k = 2
输出:false
提示:
1 <= nums.length <= 105
-109 <= nums[i] <= 109
0 <= k <= 105
思路
这道题相比于上一道题我们只需修改一下条件即可,在遇到相同元素时相减判断,若不符合,我们将之前的下标覆盖,若将整个数组插入完毕,则不存在。
代码
class Solution {
public:bool containsNearbyDuplicate(vector<int>& nums, int k) {unordered_map<int, int> hash; // 用于存储元素及其最近一次出现的索引int n = nums.size();// 遍历数组中的每个元素for (int i = 0; i < n; ++i) {// 如果当前元素已经在 hash 中存在if (hash.count(nums[i])) {// 检查当前元素的索引与最近一次出现的索引之差是否不超过 kif (i - hash[nums[i]] <= k) {return true;}}// 更新当前元素的最近一次出现的索引hash[nums[i]] = i;}// 遍历完数组都没有发现符合条件的重复元素,返回 falsereturn false;}
};
05.字母异位词分组
题目链接:https://leetcode.cn/problems/group-anagrams/
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
示例 1:
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
示例 2:
输入: strs = [""]
输出: [[""]]
示例 3:
输入: strs = ["a"]
输出: [["a"]]
提示:
1 <= strs.length <= 104
0 <= strs[i].length <= 100
strs[i]
仅包含小写字母
思路
这里使用哈希的写法可以极大的减轻我们的代码量以及简单易懂,首先我们呢将每个字符串临时排序,将哈希的key
值设为排序后的字符串,这样异位词就可以在相同的key
值后不断插入,最后我们将hash
中的value
全部导出即可。
代码
class Solution {
public:vector<vector<string>> groupAnagrams(vector<string>& strs) {unordered_map<string, vector<string>> hash; // 用于存储排序后的字符串和对应的字母异位词组for (string& s : strs) {string tmp = s;sort(tmp.begin(), tmp.end()); // 将字符串排序,使得字母异位词变得相同hash[tmp].emplace_back(s); // 将排序后的字符串作为 key,将原始字符串添加到对应的字母异位词组中}vector<vector<string>> ret;// 遍历哈希表,将每个字母异位词组添加到结果中for (auto& [k, v] : hash) {ret.emplace_back(v);}return ret;}
};
相关文章:

算法沉淀——哈希算法(leetcode真题剖析)
算法沉淀——哈希算法 01.两数之和02.判定是否互为字符重排03.存在重复元素04.存在重复元素 II05.字母异位词分组 哈希算法(Hash Algorithm)是一种将任意长度的输入(也称为消息)映射为固定长度的输出的算法。这个输出通常称为哈希…...

深入理解Redis哨兵原理
哨兵模式介绍 在深入理解Redis主从架构中Redis 的主从架构中,由于主从模式是读写分离的,如果主节点(master)挂了,那么将没有主节点来服务客户端的写操作请求,也没有主节点给从节点(slave&#…...
MySQL-存储过程(PROCEDURE)
文章目录 1. 什么是存储过程?2. 存储过程的优点3. MySQL中的变量3.1 系统变量3.2 用户自定义变量3.3 局部变量 4. 存储过程的相关语法4.1 创建存储过程(CREATE)4.2 查看存储过程(SHOW)4.3 修改存储过程(ALT…...

linux系统监控工具prometheus的安装以及监控mysql
prometheus 安装服务端客户端监控mysql prometheus浏览器查看 安装 https://prometheus.io/download/下载客户端和服务端以及需要监控的所有的包服务端 官网下载下载prometheustar -xf prometheus-2.47.2.linux-amd64.tar.gz -C /usr/local/ cd /usr/local/ mv prometheus-2.…...
初识tensorflow程序设计模式
文章目录 建立计算图tensorflow placeholdertensorflow数值运算常用的方法 tensorboard启动tensorboard的方法 建立一维与二维张量建立一维张量建立二维张量建立新的二维张量 矩阵的基本运算矩阵的加法矩阵乘法与加法 github地址https://github.com/fz861062923/TensorFlow 建…...
【QT+QGIS跨平台编译】之三十八:【GDAL+Qt跨平台编译】(一套代码、一套框架,跨平台编译)
文章目录 一、gdal介绍二、文件下载三、文件分析四、pro文件五、编译实践一、gdal介绍 GDAL(Geospatial Data Abstraction Library)是一个用于读取、写入和处理地理空间数据的开源库。它支持多种栅格和矢量地理空间数据格式,包括常见的GeoTIFF、Shapefile、NetCDF、HDF5等,…...

黑马鸿蒙教程学习1:Helloworld
今年打算粗略学习下鸿蒙开发,当作兴趣爱好,通过下华为那个鸿蒙开发认证, 发现黑马的课程不错,有视频和完整的代码和课件下载,装个devstudio就行了,建议32G内存。 今年的确是鸿蒙大爆发的一年呀,…...
蓝桥杯每日一题------背包问题(四)
前言 前面讲的都是背包的基础问题,这一节我们进行背包问题的实战,题目来源于一位朋友的询问,其实在这之前很少有题目是我自己独立做的,我一般习惯于先看题解,验证了题解提供的代码是正确的后,再去研究题解…...

OpenAI发布Sora技术报告深度解读!真的太强了!
😎 作者介绍:我是程序员洲洲,一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主、前后端开发、人工智能研究生。公粽号:洲与AI。 🎈 本文专栏:本文收录…...

AJAX——接口文档
1 接口文档 接口文档:描述接口的文章 接口:使用AJAX和服务器通讯时,使用的URL,请求方法,以及参数 传送门:AJAX阶段接口文档 <!DOCTYPE html> <html lang"en"><head><meta c…...

leetcode hot100不同路径
本题可以采用动态规划来解决。还是按照五部曲来做 确定dp数组:dp[i][j]表示走到(i,j)有多少种路径 确定递推公式:我们这里,只有两个移动方向,比如说我移动到(i,j&#x…...
【前端工程化面试题目】webpack 的热更新原理
可以在顺便学习一下 vite 的热更新原理,请参考这篇文章。 首先有几个知识点需要明确 热更新是针对开发过程中的开发服务器的,也就是 webpack-dev-serverwebpack 的热更新不需要额外的插件,但是需要在配置文件中 devServer属性中配置&#x…...

不花一分钱,在 Mac 上跑 Windows(M1/M2 版)
这是在 MacOS M1 上体验最新 Windows11 的效果: VMware Fusion,可以运行 Windows、Linux 系统,个人使用 licence 免费 安装流程见 👉 https://zhuanlan.zhihu.com/p/452412091 从申请 Fusion licence 到下载镜像,再到…...
Attempt to call an undefined function glutInit
Attempt to call an undefined function glutInit 解决方法: 从这里下载PyOpenGL 的whl安装文件, https://drive.google.com/drive/folders/1mz7faVsrp0e6IKCQh8MyZh-BcCqEGPwx 安装命令举栗 pip install PyOpenGL-3.1.7-cp39-cp39-win_amd64.whl pi…...
AB测试最小样本量
1.AB实验过程 常见的AB实验过程,分流-->实验-->数据分析-->决策:分流:用户被随机均匀的分为不同的组实验:同一组内的用户在实验期间使用相同的策略,不同组的用户使用相同或不同的策略。数据收集:…...
在Spring中事务失效的场景
在Spring框架中,事务管理是通过AOP(面向切面编程)实现的,主要依赖于Transactional注解。然而,在某些情况下,事务可能会失效。以下是一些可能导致Spring事务失效的常见场景: 非public方法&#…...
Rust 学习笔记 - 变量声明与使用
前言 任何一门编程语言几乎都脱离不了:变量、基本类型、函数、注释、循环、条件判断,这是一门编程语言的语法基础,只有当掌握这些基础语法及概念才能更好的学习 Rust。 变量介绍 Rust 是一种强类型语言,但在声明变量时…...

windows 下跑起大模型(llama)操作笔记
原贴地址:https://testerhome.com/topics/39091 前言 国内访问 chatgpt 太麻烦了,还是本地自己搭一个比较快,也方便后续修改微调啥的。 之前 llama 刚出来的时候在 mac 上试了下,也在 windows 上用 conda 折腾过,环…...

人工智能专题:基础设施行业智能化的基础设施,自智网络双价值分析
今天分享的是人工智能系列深度研究报告:《人工智能专题:基础设施行业智能化的基础设施,自智网络双价值分析》。 (报告出品方:埃森哲) 报告共计:32页 自智网络驱动的电信产业变革 经过多年的…...
docker 编译安装redis脚本
在Docker中编译安装Redis通常不是一个常见的做法,因为Redis官方提供了预编译的Docker镜像,这些镜像包含了已经编译好的Redis二进制文件。不过,如果你有特殊需求,想要自己从源代码编译Redis并打包成Docker镜像,你可以使…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...

C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...

【iOS】 Block再学习
iOS Block再学习 文章目录 iOS Block再学习前言Block的三种类型__ NSGlobalBlock____ NSMallocBlock____ NSStackBlock__小结 Block底层分析Block的结构捕获自由变量捕获全局(静态)变量捕获静态变量__block修饰符forwarding指针 Block的copy时机block作为函数返回值将block赋给…...