_5LeetCode代码随想录算法训练营第五天-C++哈希表

news2024/11/19 1:33:59

_5LeetCode代码随想录算法训练营第五天-C++哈希表

  • LeetCode 242.有效的字母异位词
  • LeetCode 349.两个数组的交集
  • LeetCode 202.快乐数
  • LeetCode 1.两数之和
    本文截图参考代码随想录:https://programmercarl.com/

哈希表

定义

哈希表是根据键值而直接进行访问的数据结构。

哈希表中键值就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:
在这里插入图片描述

哈希函数

例如要查询一个名字是否在这所学校里。–使用哈希表的时间复杂度为O(1)。

将学生姓名映射到哈希表上就涉及到了hash function ,也就是哈希函数

在这里插入图片描述

哈希碰撞

定义

当学生的数量大于哈希表的大小,此时一定会有几位学生的名字同时映射到哈希表 同一个索引下标。

在这里插入图片描述

解决方案

拉链法:小李和小王在索引1的位置发生了冲突,发生冲突的元素都被存储在链表中。

在这里插入图片描述

拉链法就是要选择适当的哈希表的大小,这样既不会因为数组空值而浪费大量内存,也不会因为链表太长而在查找上浪费太多时间。

线性探测法

使用线性探测法,一定要保证tableSize大于dataSize。 我们需要依靠哈希表中的空位来解决碰撞问题。

例如冲突的位置,放了小李,那么就向下找一个空位放置小王的信息。所以要求tableSize一定要大于dataSize ,要不然哈希表上就没有空置的位置来存放 冲突的数据了。如图所示:

在这里插入图片描述

哈希数据结构

这三种数据结构虽然实现不同,但是给用户的接口是一样的,都是和哈希表的使用方法一样。

元素数值小的时候使用数组,元素数值大的时候使用set,如果存在key重复的话使用multiset。

数组

set (集合)

对于集合,C++实现了三种容器:

在这里插入图片描述

std::unordered_set底层实现为哈希表,std::set 和std::multiset 的底层实现是红黑树,红黑树是一种平衡二叉搜索树,所以key值是有序的,key不可修改,改动key值会导致整棵树的错乱,所以只能删除和增加。

当我们要使用集合来解决哈希问题的时候,优先使用unordered_set,因为它的查询和增删效率是最优的,如果需要集合是有序的,那么就用set,如果要求不仅有序还要有重复数据的话,那么就用multiset。

map(映射)

对于映射,C++也是实现了三种容器:
在这里插入图片描述

std::map 和std::multimap 的key也是有序的,且不可更改。

当我们要使用映射来解决哈希问题的时候,优先使用unordered_map,因为它的查询和增删效率是最优的,如果需要映射是有序的,那么就用map,如果要求不仅有序还要有重复数据的话,那么就用multimap。

什么时候使用哈希表?

当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法

注意事项

使用标准库的比较好。

在这里插入图片描述

242.有效的字母异位词

本题是使用数组实现哈希表的好题。

题目

给定两个字符串 *s**t* ,编写一个函数来判断 *t* 是否是 *s* 的字母异位词。

**注意:**若 *s**t* 中每个字符出现的次数都相同,则称 *s**t* 互为字母异位词。

代码

/*
 * @lc app=leetcode.cn id=242 lang=cpp
 *
 * [242] 有效的字母异位词
 */

// @lc code=start
class Solution {
public:
    bool isAnagram(string s, string t) {
        int hash[26] = {0};//26的原因是单词的数量是26个,这里要记得初始化
        for(int i = 0; i < s.size(); i++)
            hash[s[i]-'a']++;
        for(int i = 0; i < t.size(); i++)
            hash[t[i]-'a']--;
        for(int i = 0; i < 26; i++)
            if(hash[i] != 0)
                return false;//如果哈希表中的元素不为0,也就是t与s不是字母异位词
        return true;
    }
};
// @lc code=end

349.两个数组的交集

本题是使用set实现哈希表的好题。

本题要求输出结果是不重复的。

题目

给定两个数组 nums1nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序

数组解决

整体思路

将num1转换为数组哈希表numSet,再逐个检查num2中的元素是否在numSet中,如果在,则将该元素放入结果哈希表中。

代码

/*
 * @lc app=leetcode.cn id=349 lang=cpp
 *
 * [349] 两个数组的交集
 */

// @lc code=start
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result;//初始化结果哈希表
        int numSet[1000] = {0};//初始化数组哈希表
        for(int num : nums1)//将num1转化为数组哈希表
            numSet[num] = 1;
        for(int num : nums2)//检查num2中的元素是否存在于numSet中
            if(numSet[num] == 1)
                result.insert(num);
        return vector<int>(result.begin(), result.end());
    }
};
// @lc code=end

set解决

整体思路

num1转换为哈希表,然后检查num2是否在这个哈希表中,如果在,就将该元素放入结果哈希表里(为什么用哈希表而不用数组?为了去重)。

代码

/*
 * @lc app=leetcode.cn id=349 lang=cpp
 *
 * [349] 两个数组的交集
 */

// @lc code=start
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result;//初始化结果哈希表
        unordered_set<int> numSet(nums1.begin(), nums1.end());//初始化nums1哈希表
        for(int num : nums2)//检查num2中的元素是否存在于numSet中
            if(numSet.find(num) != numSet.end())
                result.insert(num);
        return vector<int>(result.begin(), result.end());
    }
};
// @lc code=end

两种方法对比

由于此题的数据大小不是很大,因此使用数组解决耗时更低;但是当数据量很大时,建议使用set解决。

为什么遇到这样的问题不直接使用set?

直接使用set 不仅占用空间比数组大,而且速度要比数组慢。set将数值映射到key上需要做hash计算,耗时较多。

202.快乐数

题目

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

  • 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
  • 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
  • 如果这个过程 结果为 1,那么这个数就是快乐数。

如果 n快乐数 就返回 true ;不是,则返回 false

整体思路

使用一个set存储sum。

如果sum等于1,则返回true。

否则,检查sum是否重复出现,如果重复出现则说明不是快乐数,返回false。

代码

/*
 * @lc app=leetcode.cn id=202 lang=cpp
 *
 * [202] 快乐数
 */

// @lc code=start
class Solution {
public:
    int getSum(int n)
    {
        int sum = 0;
        while(n != 0)
        {
            sum += (n % 10)*(n % 10);//先将sum加上个位数的平方
            n = n / 10;//再将n/10,以便求十位数的平方,以此类推
        }
        return sum;
    }
    bool isHappy(int n) {
        int sum = getSum(n);
        unordered_set<int> sumSet;
        while(1)
        {
            if(sum == 1)//如果所得sum==1,说明该数为快乐数,返回true
                return true;
            else
            {
                if(sumSet.find(sum) == sumSet.end())//如果在sumSet中找不到sum,则将sum插入sumSet
                    sumSet.insert(sum);
                else//否则,说明不是快乐数,返回false
                    return false;
            }
            sum = getSum(sum);//反复获得sum值
        }        
    }
};
// @lc code=end

1.两数之和

题目

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

整体思路

要使用map,存储遍历过的元素和其下标,元素作为键值,下标作为值。

逐个遍历所有元素,在map中找,有没有元素与当前元素相加等于target,如果找到了,就返回两者的下标;否则,返回{}数组。

代码

/*
 * @lc app=leetcode.cn id=1 lang=cpp
 *
 * [1] 两数之和
 */

// @lc code=start
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> map;
        for(int i = 0; i < nums.size(); i++)//遍历所有元素
        {
            auto it = map.find(target - nums[i]);//这个返回值的类型是个迭代器
            if(it != map.end())//如果map中存在这样的数,就返回两者的索引
                return {i, it->second};
            //如果没有这样的数的话,就将当前nums及其索引插入map(值为键值,索引为值),继续遍历nums
            map.insert(pair<int,int>(nums[i], i));
        }
        return {};
    }
};
// @lc code=end

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

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

相关文章

shell 创建子进程及并行延时执行命令方法

shell 创建子进程方法 1. 什么是shell子进程 子进程&#xff0c;是从父子进程的概念出发的&#xff0c;unix操作系统的进程从init进程开始&#xff08;init进程为1,而进程号0为系统原始进程&#xff0c;以下讨论的进程原则上不包括进程0)均有其对应的子进程&#xff0c;就算是…

POI通过模板导出excel(包含表头合并处理)

最近接触到比较多poi相关的需求&#xff0c;总结一下通过模板导出以及表头合并的一些复杂情况处理。 简单使用的话可以参考下我之前写的 POI实现导入导出excel 目录&#xff1a;1、POI通过模板导出2、POI表头合并处理1、POI通过模板导出 其实通过模板导出的原理&#xff0c;无…

2021 年年度最佳开源软件

Svelte https://svelte.dev/ Svelte 是一种全新的构建用户界面的方法。传统框架如 React 和 Vue 在浏览器中需要做大量的工作&#xff0c;而 Svelte 将这些工作放到构建应用程序的编译阶段来处理。 与使用虚拟&#xff08;virtual&#xff09;DOM 差异对比不同。Svelte 编写的…

DAla-Gly-Gly,77286-90-9

Substrate for bacterial D-aminopeptidases.细菌d -氨基肽酶的底物。 编号: 191616中文名称: 三肽DAla-Gly-Gly英文名: DAla-Gly-GlyCAS号: 77286-90-9单字母: H2N-DAla-GG-OH三字母: H2N-DAla-Gly-Gly-COOH氨基酸个数: 3分子式: C7H13N3O4平均分子量: 203.2精确分子量: 203.0…

虚拟现实 VR 碰撞 3D 可视化,图扑打造一体化管控平台

工信部《虚拟现实产业发展白皮书 5.0 》中明确提出&#xff1a;“通过财政资金促进虚拟现实技术产业化&#xff0c;支持面向工业、文化、教育等重点行业的虚拟现实技术应用”。 虚拟现实 VR 技术以用户体验视角为中心&#xff0c;跟踪反馈在 3D 场景中的动作&#xff0c;借助软…

kali工具学习

目录 1.waybackurls 网络爬虫&#xff0c;url搜索 2.wafw00f 检测网站用了什么waf 3.theHarvester ip、邮箱、host搜集 4. oneforall 子域名搜集 5. nmap kali自带的扫描工具 6. whatweb 指纹查询 1.waybackurls 网络爬虫&#xff0c;url搜索 2.wafw00f 检测网…

阿里巴巴注册中心nacos

目录 一、配置中心介绍 1、Spring Cloud Config 2、Nacos替换Config &#xff08;1&#xff09;应用场景 二、读取Nacos配置中心的配置文件 1、在Nacos创建统一配置文件 2、以service-statistics模块为例 3、补充&#xff1a;springboot配置文件加载顺序 三、名称空间…

网络实验之VRRP协议

一、VRRP协议简介 虚拟路由冗余协议(Virtual Router Redundancy Protocol&#xff0c;简称VRRP)是由IETF提出的解决局域网中配置静态网关出现单点失效现象的路由协议。VRRP是一种路由容错协议&#xff0c;也可以叫做备份路由协议。一个局域网络内的所有主机都设置缺省路由&…

MySQL入门阶段这一篇就够了-学习笔记(手敲1.5万字)

前言 虽然在大一下学期&#xff0c;就已经接触到了MySQL&#xff0c;但是那个时候只是会用MySQL进行增删改查&#xff0c;在大三上学期&#xff0c;尝试投简历寻找实习时&#xff0c;对方公司对于程序员的MySQL水平有很高的要求&#xff0c;所以我开始系统化的学习MySQL。顺便…

想写出复用性强的组件?快来试试 Storybook 吧

简介 Storybook 是 UI 组件的开发环境&#xff0c;它允许开发者浏览组件库&#xff0c;查看每个组件的不同状态&#xff0c;以及交互地开发和测试组件。 Storybook 可帮助你记录组件以供重用&#xff0c;并自动对组件进行可视化测试以防止出现错误。 开始 在对 Storybook 有…

halcon measure_pos和measure_pairs详解

这两个算子作为halcon一维测量的关键&#xff0c;看了这两个算子的多个博客&#xff0c;也没搞清楚里面几个参数的意义和测量的原理&#xff0c;决定自己详细试一下&#xff0c;将测试的过程详细记录下来&#xff0c;供以后需要参考的朋友使用&#xff0c;本文将从以下几个点说…

使用bat脚本运行python脚本,bat出现闪退,怎么解决?

前言 本文是该专栏的第4篇,后面会持续分享python的各种干货知识,值得关注。 工作上为了方便,很多时候我们会设置一个bat脚本来双击运行python脚本,这样既方便又能在工作上节约大量时间。 但是,你或许会碰到这样的情况,当双击bat脚本的时候,bat窗口界面会直接出现闪退关…

DM8设置自动备份,达梦数据库,自动备份。详细步骤。常用命令,启动关闭数据库,查看DMAP状态

常用命令 DmServiceDAMENG.service改成自己bin目录下文件名 运维常见问题&#xff0c;官方文档 注意事项 登录客户端工具&#xff0c;一定要使用SYSDBA用户进行下面的客户端操作 登录数据库主机&#xff0c;一定要使用安装数据库时创建的dmdba用户 定时备份前请先配置本地…

引入新模块都在用这个注解,它是如何生效的?|原创

本文讲解了Enable 类注解是如何生效的以及其核心注解 Import 的原理&#xff0c;并且用 EnableAsync 注解来举例。点击上方“后端开发技术”&#xff0c;选择“设为星标” &#xff0c;优质资源及时送达在项目开发的过程中&#xff0c;我们会遇到很多名字为 Enablexxx 的注解&a…

OA系统解决方案

一、OA系统解决方案介绍 OA系统&#xff0c;即办公自动化系统&#xff08;Office Assistant简称OA&#xff09;&#xff0c;它是一个集成了企业信息发布、公文与信息管理、公文处理、知识管理、内部通讯、协同办公等办公与管理应用功能一体的协同 办公系统。OA系统解决方案则是…

Linux——详解共享内存shared memory

目录 一.共享内存介绍 &#xff08;一&#xff09;.什么是共享内存 &#xff08;二&#xff09;.共享内存优点 &#xff08;三&#xff09;.共享内存缺点 二.共享内存使用 &#xff08;一&#xff09;.创建—shmget ①key ②size ③shmflg ④返回值 &#xff08;二&…

CRMEB电商商城系统腾讯云ECS服务器安装配置搭建教程文档

一、推荐使用宝塔Linux面板&#xff0c;简单好用。二、放行服务器端口。详细步骤&#xff1a; 1.登录腾讯云服务器&#xff0c;点击右上角“控制台” 2.我的资源&#xff0c;点击进入云服务器 3.进入实例列表&#xff0c;选择您要安装的服务器&#xff0c;点击更多 4.选择重装…

Hadoop 如何保证自己的江湖地位?Yarn 功不可没

前言 任何计算任务的运行都离不开计算资源&#xff0c;比如 CPU、内存等&#xff0c;那么如何对于计算资源的管理调度就成为了一个重点。大数据领域中的 Hadoop 之所以一家独大&#xff0c;深受市场的欢迎&#xff0c;和他们设计了一个通用的资源管理调度平台 Yarn 密不可分&a…

Metal每日分享,四维向量偏移滤镜效果

本案例的目的是理解如何用Metal实现图像4维向量颜色效果滤镜,通过对像素点颜色进行4维向量叠加运算得到新的像素点; Demo HarbethDemo地址实操代码 // 暖色系 let filter = C7ColorVector4(vector: Vector4.Color.warm)// 方案1: ImageView.image = try? BoxxIO(element: o…

浅谈字节码增强技术系列1-字节码增强概览

作者&#xff1a;董子龙 前言 前段时间一直想参照lombok的实现原理写一篇可以生成业务单据修改记录插件的专利&#xff0c;再查阅资料的过程中&#xff0c;偶然了解到了字节码增强工具-byteBuddy。但是由于当时时间紧促&#xff0c;所以没有深入的对该组件进行了解。其实再我…