算法沉淀——哈希算法(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) <= 1000 <= 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] <= 1090 <= 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 <= 1040 <= strs[i].length <= 100strs[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镜像,你可以使…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
