算法沉淀——哈希算法(leetcode真题剖析)

news2024/11/29 4:52:04

在这里插入图片描述

算法沉淀——哈希算法

  • 01.两数之和
  • 02.判定是否互为字符重排
  • 03.存在重复元素
  • 04.存在重复元素 II
  • 05.字母异位词分组

哈希算法(Hash Algorithm)是一种将任意长度的输入(也称为消息)映射为固定长度的输出的算法。这个输出通常称为哈希值或摘要。哈希算法的主要目的是快速、高效地检索数据,因为哈希值可以用作数据的唯一标识。

哈希算法的特点包括:

  1. 固定输出长度: 无论输入的数据大小如何,哈希算法都会生成固定长度的哈希值。
  2. 快速计算: 对于给定的输入,哈希算法应该迅速生成相应的哈希值。
  3. 不可逆性: 从哈希值不能逆向推导出原始输入的内容。即使输入的数据发生微小变化,生成的哈希值也应该是大不相同的。
  4. 雪崩效应: 输入数据的微小变化应该导致输出哈希值的巨大变化,以确保输入数据的任何改变都能产生不同的哈希值。

在算法题中,哈希算法有许多实际运用。以下是一些常见的应用场景:

  1. 查找和检索: 使用哈希表(HashMap)来快速查找元素。通过将元素的键映射到哈希表中的索引,可以在常量时间内执行查找操作。
  2. 去重: 利用哈希集合(HashSet)来检测和删除重复元素。通过将元素的哈希值映射到集合中,可以轻松检测是否已经存在相同的元素。
  3. 缓存: 使用哈希表来实现缓存,以快速检索先前计算的结果。这种方法被称为缓存哈希。
  4. 字符串匹配: 使用哈希算法来加速字符串匹配过程。例如,Rabin-Karp字符串匹配算法使用哈希值来比较字符串,以快速检测是否匹配。
  5. 数据校验: 哈希算法用于验证数据的完整性。通过生成数据的哈希值并将其与已知的哈希值进行比较,可以确保数据在传输或存储过程中没有被篡改。
  6. 分布式系统: 在分布式系统中,哈希算法被用于负载均衡和数据分片。通过将资源或数据的标识哈希到一组节点上,可以实现均匀分布和高效的访问。
  7. 密码学: 在密码学中,哈希算法用于生成密码的摘要,以便安全地存储密码或验证用户身份。
  8. 图算法: 在图算法中,哈希算法可用于快速判断两个图是否相同或是否存在同构关系。

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/

给定两个由小写字母组成的字符串 s1s2,请编写一个程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。

示例 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) {
        // 如果两个字符串长度不相等,直接返回 false
        if(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 中不存在或出现次数已经用尽,返回 false
            if(hash[c - 'a'] == 0) {
                return false;
            }
            hash[c - 'a']--; // 减少字符 c 在 s1 中的出现次数
        }

        // 如果遍历完 s2 后每个字符在 s1 中的出现次数都匹配,返回 true
        return 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 中存在,说明数组包含重复元素,返回 true
            if(hash.count(i)) {
                return true;
            }
            // 将当前元素插入到 hash 中
            hash.insert(i);
        }

        // 如果遍历完数组都没有发现重复元素,返回 false
        return false;
    }
};

04.存在重复元素 II

题目链接:https://leetcode.cn/problems/contains-duplicate-ii/

给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个 不同的索引 ij ,满足 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])) {
                // 检查当前元素的索引与最近一次出现的索引之差是否不超过 k
                if (i - hash[nums[i]] <= k) {
                    return true;
                }
            }
            // 更新当前元素的最近一次出现的索引
            hash[nums[i]] = i;
        }
        // 遍历完数组都没有发现符合条件的重复元素,返回 false
        return 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;
    }
};

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

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

相关文章

2024.2.8

1. 现有文件test.c\test1.c\main.c,编写Makkefile Makefile&#xff1a; CCgcc EXEa.out OBJS$(patsubst %.c,%.o,$(wildcard *.c)) CFLAGS-c -oall:$(EXE)$(EXE):$(OBJS)$(CC) $^ -o $%.o:%.c$(CC) $(CFLAGS) $ $^.PHONY:cleanclean:rm $(OBJS) $(EXE) 2. C编程实现&#x…

HarmonyOS鸿蒙学习基础篇 - Column/Row 组件

前言 Row和Column组件是线性布局容器&#xff0c;用于按照垂直或水平方向排列子组件。Row表示沿水平方向布局的容器&#xff0c;而Column表示沿垂直方向布局的容器。这些容器具有许多属性和方法&#xff0c;可以方便地管理子组件的位置、大小、间距和对齐方式。例如&#xff0c…

netstat命令

netstat 是一个计算机网络命令行工具&#xff0c;用于显示网络连接、路由表和网络接口等网络相关信息。netstat 命令可以在各种操作系统上使用&#xff0c;包括 Windows、Linux 和 macOS 等。 在使用 netstat 命令时&#xff0c;可以提供不同的选项来显示不同类型的网络信息。…

【北邮鲁鹏老师计算机视觉课程笔记】08 texture 纹理表示

【北邮鲁鹏老师计算机视觉课程笔记】08 texture 纹理表示 1 纹理 规则和不规则的 2 纹理的用处 从纹理中恢复形状 3 分割与合成 4 分析纹理进行分类 通过识别纹理分析物理性质 如何区分纹理 5 寻找有效的纹理分类方法 发现模式、描述区域内模式 A对应图2 B对应图…

Linux命令行全景指南:从入门到实践,掌握命令行的力量

目录 知识梳理思维导图&#xff1a; linux命令入门 为什么要学Linux命令 什么是终端 什么是命令 关于Linux命令的语法 tab键补全 关于命令提示符 特殊目录 常见重要目录 /opt /home /root /etc /var/log/ man命令 shutdown命令 history命令 which命令 bash…

单链表的介绍

一.单链表的概念及结构 概念&#xff1a;链表是⼀种物理存储结构上⾮连续、⾮顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表 中的指针链接次序实现的 。 结构&#xff1a;根据个人理解&#xff0c;链表的结构就像火车厢一样&#xff0c;一节一节连在一起的&#x…

ClickHouse--07--SQL DDL 操作

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 SQL DDL 操作1 创建库2 查看数据库3 删除库4 创建表5 查看表6 查看表的定义7 查看表的字段8 删除表9 修改表9.1 添加列9.2 删除列9.3 清空列9.4 给列修改注释9.5 修…

深入解析Elasticsearch的内部数据结构和机制:行存储、列存储与倒排索引之倒排索引(三)

当我们谈论Elasticsearch&#xff08;简称ES&#xff09;时&#xff0c;我们经常会提到它的高效搜索能力。而这背后的核心技术之一就是倒排索引。那么&#xff0c;什么是倒排索引&#xff0c;以及它是如何在Elasticsearch中工作的呢&#xff1f; 深入解析Elasticsearch的内部数…

机器学习系列——(二十一)神经网络

引言 在当今数字化时代&#xff0c;机器学习技术正日益成为各行各业的核心。而在机器学习领域中&#xff0c;神经网络是一种备受瞩目的模型&#xff0c;因其出色的性能和广泛的应用而备受关注。本文将深入介绍神经网络&#xff0c;探讨其原理、结构以及应用。 一、简介 神经网…

PHP脉聊交友系统网站源码,可通过广告变现社交在线聊天交友即时通讯APP源码,附带视频搭建教程

探索全新社交体验&#xff1a;一站式PHP交友网站解决方案 &#x1f310; 全球化交友&#xff0c;无界沟通 在数字化的浪潮下&#xff0c;社交已不再受地域限制。我们的PHP交友网站不仅支持多国语言&#xff0c;还配备了即时翻译功能&#xff0c;让您轻松跨越语言障碍&#xff…

分享87个CSS3特效,总有一款适合您

分享87个CSS3特效&#xff0c;总有一款适合您 87个CSS3特效下载链接&#xff1a;https://pan.baidu.com/s/1CAxe8nPBzXvH7Nr6B_U72Q?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不…

MySQL基本操作之数据库的操作

一.创建数据库 1.基本语法 create database 数据库名&#xff1b; 注意别忘记加分号。 2.if not exists 数据库名字是唯一的&#xff0c;所以不可以创建已存在的数据库&#xff0c;如下&#xff1a; 重复创建就会报错 所以有了if not exists这个语法&#xff0c;加上之后&…

片上网络NoC(5)——非直连拓扑

目录 一、前言 二、概念阐述 三、交叉开关 四、蝶形网络 五、clos网络 六、fat tree网络 6.1 clos网络的折叠过程 七、总结 一、前言 本文继续介绍片上网络的拓扑&#xff0c;在之前的文章中&#xff0c;我们已经介绍了片上网络的拓扑指标和直连拓扑的相关内容&#xf…

正月初五迎财神

大家好&#xff0c;我是小悟 正月初五&#xff0c;人们在这一天迎接财神&#xff0c;祈求财运亨通、事业顺利。按照习俗&#xff0c;家家户户都会燃放鞭炮、点灯笼、摆设祭品&#xff0c;以示虔诚。 早晨&#xff0c;太阳刚刚升起&#xff0c;大家便早早起床&#xff0c;开始准…

软件架构与系统架构:区别与联系的分析

软件架构与系统架构&#xff1a;区别与联系的分析 在信息技术领域&#xff0c;软件架构和系统架构这两个术语经常被提及。尽管它们在某些方面有重叠&#xff0c;但它们确实代表了不同的概念和聚焦点。理解这两种架构之间的区别和联系对于任何从事技术开发和设计的专业人士都是至…

【Python网络编程之TCP三次握手】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;Python开发技术 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; Python网络编程之[TCP三次握手] 代码见资源&#xff0c;效果图如下一、实验要求二、协议原理2.…

DS Wannabe之5-AM Project: DS 30day int prep day15

Q1. What is Autoencoder? 自编码器是什么&#xff1f; 自编码器是一种特殊类型的神经网络&#xff0c;它通过无监督学习尝试复现其输入数据。它通常包含两部分&#xff1a;编码器和解码器。编码器压缩输入数据成为一个低维度的中间表示&#xff0c;解码器则从这个中间表示重…

WPF是不是垂垂老矣啦?平替它的框架还有哪些

WPF&#xff08;Windows Presentation Foundation&#xff09;是微软推出的一种用于创建 Windows 应用程序的用户界面框架。WPF最初是在2006年11月推出的&#xff0c;它是.NET Framework 3.0的一部分&#xff0c;为开发人员提供了一种基于 XAML 的方式来构建丰富的用户界面。 W…

小白学Halcon100例:如何应用极坐标的展开及逆变换?

这里写目录标题 什么是极坐标系?在halcon中对应的算子halcon实例程序输出结果:原图什么是极坐标系? 1、极坐标系(polar coordinates)是指在平面内由极点、极轴和极径组成的坐标系。在平面上取定一点O,称为极点。从O出发引一条射线Ox,称为极轴。再取定一个单位长度,通常…

微服务OAuth 2.1认证授权Demo方案(Spring Security 6)

文章目录 一、介绍二、auth微服务代码1. SecurityConfig2. UserDetailsService3. 总结 三、gateway微服务代码1. 统一处理CORS问题 四、content微服务代码1. controller2. SecurityConfig3. 解析JWT Utils4. 总结 五、一些坑 书接上文 微服务OAuth 2.1认证授权可行性方案(Sprin…