LeetCode 热题100之哈希
1.两数之和

思路分析1(暴力法)
- 双重循环枚举满足num[i] + nums[j] = = target的索引,刚开始不知道如何返回一对索引。后来知道可以直接通过return {i,j}返回索引;
- 注意:j应该从i+1处开始,避免使用两次相同的元素;
- 如果没有找到,则需要返回空return{};
- 时间复杂度: o ( N 2 ) , o(N^2), o(N2),其中N是数组中的元素数量。最坏情况下数组中任意两个数都要被匹配一次;
具体实现代码(详解版):
class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {int l = nums.size(); // 获取数组的长度// 外层循环遍历数组中的每个元素for (int i = 0; i < l; i++) {// 内层循环从下一个元素开始遍历for (int j = i + 1; j < l; j++) {// 检查当前两个元素的和是否等于目标值if (nums[i] + nums[j] == target) {// 如果找到了,返回这两个元素的索引return {i, j};}}}// 如果没有找到满足条件的元素,返回空的 vectorreturn {};}
};
思路分析2(哈希表优化)
- 遍历数组:对每个元素 nums[i],计算它的补数 target - nums[i];
- 查找补数:使用 hashtable.find() 方法检查补数是否已存在于哈希表中;
- 返回索引:如果找到了补数,就返回补数的索引和当前索引i;
- 更新哈希表:如果未找到补数,则将当前元素及其索引存入哈希表
样例模拟:
对于 nums = [2, 7, 11, 15] 和 target = 9,我们使用twoSum 函数来找到两个数的索引,使它们的和等于目标值。
1.第一轮迭代(i= 0)
- 当前元素 nums[0] = 2,补数为 9 - 2 = 7;
- 哈希表中没有 7,所以将 2 存入哈希表:hashtable[2] = 0;
2.第二轮迭代(i =1):
- 当前元素 nums[1] = 7,补数为 9 - 7 = 2。
- 在哈希表中找到 2,其索引为 0;
- 返回 {0, 1},表示 nums[0] 和 nums[1] 的和等于 9。
具体实现代码(详解版):
class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {unordered_map<int, int> hashtable; // 创建哈希表,存储数字及其索引// 遍历数组中的每个元素for (int i = 0; i < nums.size(); i++) {// 计算当前数字的补数int complement = target - nums[i];// 在哈希表中查找补数auto it = hashtable.find(complement);if (it != hashtable.end()) {// 如果找到了补数,返回其索引和当前索引return {it->second, i};}// 将当前数字及其索引存入哈希表hashtable[nums[i]] = i;}// 如果没有找到,返回空的 vectorreturn {};}
};
2.字母异位词分组

思路分析1(字母排序)
- 理解字母异位词:两个字符串互为字母异位词,当且仅当两个字符串包含的字母相同。

- 需要根据特征进行归类,就应该利用哈希表;
- 由于互为字母异位词的两个字符串包含的字母相同,因此对两个字符串分别进行排序之后得到的字符串一定是相同的,故可以将排序之后的字符串作为哈希表的键,哈希表的值为一组字母异位词列表。
-
- 哈希表:使用 unordered_map 来存储排序后的字符串作为键,原字符串作为值的列表。
-
- 字符串排序:通过排序将字母异位词归为同一键。
-
- 结果构造:将哈希表中的每个值(异位词组)添加到结果向量中。
具体实现代码(详解版):
class Solution {
public:vector<vector<string>> groupAnagrams(vector<string>& strs) {unordered_map<string, vector<string>> mp; // 哈希表,存储异位词组// 遍历每个字符串for (string& str : strs) {string key = str; // 复制当前字符串sort(key.begin(), key.end()); // 将字符串排序,作为哈希表的键mp[key].push_back(str); // 将原字符串加入对应的组}vector<vector<string>> ans; // 存储结果for (auto it = mp.begin(); it != mp.end(); ++it) {ans.push_back(it->second); // 将每组异位词添加到结果中}return ans; // 返回结果}
};
复杂度分析:
- 时间复杂度:O(nklogk),其中 n 是 strs 中的字符串的数量,k 是 strs 中的字符串的的最大长度。需要遍历 n 个字符串,对于每个字符串,需要 O(klogk) 的时间进行排序以及 O(1) 的时间更新哈希表,因此总时间复杂度是 O(nklogk)。
3.128最长连续序列

思路分析1(先排序,虽然不符合 O ( n ) O(n) O(n)的时间复杂度吗,但是是最快的)
- 先对数组进行排序;
- 然后判断是否是连续序列
-
- 如果差1,即是连续的数字,更新最长序列长度
-
- 如果它们相等(重复),则可以忽略,不需要修改 mx
- 否则,说明当前数字与之前的连续序列断开了。需要重置当前序列长度 mx 为 1,因为当前数字本身可以视为新的序列的开始。
具体实现代码(详解版)
class Solution {
public:int longestConsecutive(vector<int>& nums) {if(nums.size() == 0) return 0; // 如果数组为空,返回 0int ans = 1, mx = 1; // 初始化最长序列长度和当前序列长度sort(nums.begin(), nums.end()); // 对数组进行排序for(int i = 1; i < nums.size(); i++) {if(nums[i - 1] + 1 == nums[i]) { // 如果是连续的数字ans = max(ans, ++mx); // 更新最长序列长度}else if(nums[i - 1] == nums[i]) { continue; // 跳过重复数字}else {mx = 1; // 重置当前序列长度}}return ans; // 返回最长连续序列的长度}
};
2.思路分析2:使用哈希集合(优化为 O ( n ) O(n) O(n))
-
使用 unordered_set 存储输入数组中的所有数字。这允许我们在 O(1) 的时间内快速查找任意数字。
-
通过 for 循环遍历 numSet 中的每个数字,检查它是否是一个潜在的连续序列的起点。
-
确定起始点:
- 通过 numSet.find(num - 1) == numSet.end() 检查当前数字 num 是否是一个连续序列的起点。
- 如果 num - 1 不在集合中,说明 num 是一个新的序列的开始。
-
查找连续序列
- 如果 num 是起始数字,初始化 currentNum 为 num,并将 currentStreak 设为 1(表示当前序列的长度)。
- 使用 while 循环,查找 currentNum + 1 是否存在于集合中。如果存在,则 currentNum 自增,并且 currentStreak 增加 1,直到没有连续的数字为止。
-
更新最长序列长度:在每次找到一个完整的连续序列后,将 longestStreak 更新为当前序列长度和已有最长序列长度的较大值。
-
最后,返回 longestStreak,即数组中最长连续序列的长度
具体实现代码(详解版):
class Solution {
public:int longestConsecutive(vector<int>& nums) {// 使用 unordered_set 存储所有数字unordered_set<int> numSet(nums.begin(), nums.end());int longestStreak = 0;// 遍历每个数字for (int num : numSet) {// 只从未处理的起始数字开始查找//如果 num - 1 不在集合中,说明 num 是一个新的序列的开始。if (numSet.find(num - 1) == numSet.end()) {int currentNum = num;int currentStreak = 1;// 向上查找连续的数字while (numSet.find(currentNum + 1) != numSet.end()) {currentNum++;currentStreak++;}// 更新最长序列长度longestStreak = max(longestStreak, currentStreak);}}return longestStreak; // 返回最长连续序列的长度}
};

这是两种算法的通过时间,使用算法1的竟然还快一点~(hhhh)
总结:哈希表(集合)常常用于解决与查找、计数或分组相关的问题,在数据结构和算法中广泛应用,如实现字典、集合等。哈希表是一种高效且灵活的数据结构,适合于多种场景,尤其是当需要快速查找、插入和删除时。理解其原理和使用方式可以帮助解决许多实际问题。
相关文章:
LeetCode 热题100之哈希
1.两数之和 思路分析1(暴力法) 双重循环枚举满足num[i] nums[j] target的索引,刚开始不知道如何返回一对索引。后来知道可以直接通过return {i,j}返回索引;注意:j应该从i1处开始,避免使用两次相同的元素…...
软工——模块设计(爱啦爱啦)
过程设计的工具 一、程序流程图 程序流程图又称为程序框图,它是历史最悠久、使用最广泛的描述过程设计的方法。 它的主要优点是对控制流程的描绘很直观,便于初学者掌握。 程序流程图历史悠久,至今仍在广泛使用着。 程序流程图的主要缺点&a…...
Xmind一款极简思维导图和头脑风暴软件,支持PC和移动端,Xmind 2024.10.01101版本如何升级到Pro版?简单操作,最新可用!
文章目录 Xmind下载安装Xmind免费升级到Pro Xmind 是一款全功能的思维导图和头脑风暴软件,不限制节点和文件数,创新无限,界面纯净简洁无广告,支持PC和移动端,思维导图和大纲视图自由切换,可本地化文档存储&…...
自动化工具:Ansible
目录 一、运维自动化工具有哪些 二、Ansible 概述 1、Ansible 概念 2、Ansible 特点 3、Ansible 工作流程 三、安装部署Ansible 1、环境部署 2、管理节点安装 Ansible 3、查看Ansible相关文件 4、配置主机清单 5、免密管理 ssh-keygen 5.1、测试连通性 5.2、简洁输…...
我是类(最终版)
文章目录 再看构造函数类型转换static静态成员友元内部类匿名对象对象拷贝时的编译器优化 再看构造函数 本标题的目的是解决如下问题:当实现MyQueue时,我们不需要写默认构造函数,因为编译器会调用Stack的默认构造,但是࿰…...
详解ip route
ip route命令用于查看 Linux 系统中的路由表信息。 路由表包含的主要信息 目标网络地址(Destination) 显示网络的目标地址,可以是一个具体的网络地址(如192.168.1.0/24),也可以是一个默认网络(…...
OpenGL进阶系列04 - OpenGL 点精灵
一:概述 OpenGL 点精灵是一种渲染技术,用于在3D场景中渲染小的、可缩放的点。它们通常用于表示粒子效果、光源或其他小物体。点精灵会根据视图和投影矩阵自动调整大小,使其始终在屏幕上保持一致的视觉效果。实现时,点精灵通常通过使用纹理和适当的着色器来增加视觉效果。 …...
VSCode按ctrl与鼠标左键无法实现跳转的解决办法
vscode编译环境老是出问题,下面介绍两种解决方法 需要提前配置好代码编译需要的库以及编译器位置等等。 ctrlshiftp,输入 >C/C配置(JSON) 打开生成的c_cpp_properties.json {"configurations": [{"name": "Li…...
U盘数据丢失不用慌,这4个工具可以帮你恢复。
因为将大量的数据存到U盘里面很方便,所以U盘使用也很广泛。但是里面的数据丢失想必很多朋友都碰到过,不过现在有很多方法都可以帮助大家将数据回顾回来。这里我便筛选了几款比较好的数据恢复工具,在这里跟大家分享。 1、福昕U盘恢复软件 直通…...
如何在Ubuntu上挂载一块硬盘:详解方案与实操步骤【小白无坑版】
如何在Ubuntu上挂载一块硬盘:详解方案与实操步骤 一、引言 在日常的开发或使用中,我们经常会遇到这样的场景:系统硬盘空间不足,需要额外挂载一块硬盘以扩展存储;或者我们需要将一块新硬盘用于专门存储数据或备份项目…...
【JAVA】第三张_Eclipse下载、安装、汉化
简介 Eclipse是一种流行的集成开发环境(IDE),可用于开发各种编程语言,包括Java、C、Python等。它最初由IBM公司开发,后来被Eclipse Foundation接手并成为一个开源项目。 Eclipse提供了一个功能强大的开发平台&#x…...
go-zero系列-限流(并发控制)及hey压测
参考地址: go-zero系列-限流(并发控制):https://go-zero.dev/docs/tutorials/service/governance/limiter hey地址:https://github.com/rakyll/hey1、压测工具hey下载安装: 会安装到GOPATH/bin目录下 go install github.com/ra…...
Electron-(三)网页报错处理与请求监听
在前端开发中,Electron 是一个强大的框架,它允许我们使用 Web 技术构建跨平台的桌面应用程序。在开发过程中,及时处理网页报错和监听请求是非常重要的环节。本文将详细介绍 Electron 中网页报错的日志记录、webContents 的监听事件以及如何监…...
银河麒麟(debian)下安装postgresql、postgis
1、安装postgresql、postgis sudo apt update sudo apt install postgresql postgresql-contrib sudo apt install postgis postgresql-12-postgis-32、创建一个使用postgis的数据库 sudo -i -u postgres #postgres管理员用户createdb gisdb #创建新的gisdb数据库 psql -d gi…...
【已解决】【Hadoop】 Shell命令易错点及解决方法
Hadoop是一个强大的分布式系统,用于处理大规模数据集。在使用Hadoop的过程中,熟练掌握其Shell命令是必不可少的。本文将介绍几个常用的Hadoop Shell命令,并总结一些常见的操作错误及其解决方法。 Hadoop Shell命令简介 Hadoop提供了多种She…...
ST7789读取ID错误新思路(以STC32G为例)
1.前言 前两天刚把ST7789写入搞定,这两天想折腾一下读取。最开始是读ID,先是用厂家送的程序,程序里面用的是模拟I8080协议,一切正常。后来我用STC32G的内置LCM模块,发现读取不出来。更神奇的是ID读不出来,…...
【MySQL】入门篇—基本数据类型:使用ORDER BY进行排序
MySQL作为一种流行的关系数据库管理系统,提供了强大的数据查询功能,其中ORDER BY子句用于对查询结果进行排序。排序可以帮助用户更直观地查看数据,发现趋势或异常,尤其在处理大量数据时尤为重要。 应用场景: 用户管理…...
java线程池bug的一些思考
科学需要对前人的怀疑,对权威的怀疑。 但是上学的时候,我们也需要去理解课本。 现在网上充斥了“java 线程池的缺点”这一观点。分析了一下线程池的工作原理,确实也存在这些问题。 Java线程池工作原理。核心线程数,最大线程数&…...
深入解析浮动布局及其在现代Web开发中的应用与替代(浮动的概念及应用、如何清除浮动、使用Flex布局和Grid布局的区别、使用`float`布局的历史和现状)
文章目录 1. 引言2. 浮动的概念及应用3. 如何清除浮动4. 使用Flex布局和Grid布局的区别5. 使用float布局的历史和现状6. 综合案例展示7. 结论8. 建议 1. 引言 在CSS布局的历史中,float属性曾是网页布局的主要工具之一。然而,随着现代布局技术࿰…...
WPF基础权限系统
一.开发环境 VisualStudio 2022NET SDK 8.0Prism 版本 8.1.97Sqlite 二. 功能介绍 WPF 基础权限系统,是一个支持前后端分离设计的 客户端(C/S)项目,该示例项目前端xaml使用UI库 ,Material Design Themes UI 来构建用户界面,确保…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
实战设计模式之模板方法模式
概述 模板方法模式定义了一个操作中的算法骨架,并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下,重新定义算法中的某些步骤。简单来说,就是在一个方法中定义了要执行的步骤顺序或算法框架,但允许子类…...
