代码随想录刷题题Day5

刷题的第五天,希望自己能够不断坚持下去,迎来蜕变。😀😀😀
刷题语言:C++ / Python
Day5 任务
● 哈希表理论基础
● 242.有效的字母异位词
● 349. 两个数组的交集
● 202. 快乐数
● 1. 两数之和

1 哈希表理论基础

当我们遇到要快速判断一个元素是否出现在集合里,就要考虑哈希法
哈希表:根据关键码的值而直接进行访问的数据结构(和数组根据索引下标查找的原理一样)
(1)哈希函数
哈希函数,把学生的姓名直接映射为哈希表上的索引,然后就可以通过查询索引下标快速知道这位同学是否在这所学校里

哈希函数通过hashCode把名字转化为数值,一般hashcode是通过特定编码方式,可以将其他数据格式转化为不同的数值,这样就把学生名字映射为哈希表上的索引数字
在这里插入图片描述

如果hashCode得到的数值大于哈希表的大小,为了保证映射出来的索引数值都落在哈希表上,会在再次对数值做一个取模的操作,就保证了学生姓名一定可以映射到哈希表上。

❓如果学生的数量大于哈希表的大小怎么办,此时就算哈希函数计算的再均匀,避免不了会有几位学生的名字同时映射到哈希表同一个索引下标的位置,这个现象叫做哈希碰撞

(2)哈希碰撞
在这里插入图片描述
两种解决办法:拉链法线性探测法
拉链法:
在这里插入图片描述

位置发生冲突,将发生冲突的元素存储在链表中,就可以通过索引找到小李、小王

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

线性探测法:
在这里插入图片描述
使用该方法的前提:保证tableSize大于dataSize,依靠哈希表的空位解决碰撞问题
(3)常见的三种哈希结构
使用哈希法来解决问题,一般选择如下三种数据结构:

(1)数组
(2)set (集合)
(3)map(映射)

在C++中,set提供以下三种数据结构,底层实现以及优劣如下表所示
在这里插入图片描述

std::unordered_set底层实现是哈希表,std::set和std::multiset底层实现是红黑树,红黑树是平衡二叉搜索树,所以key值有序,但key值不可修改,只能删除和增加

map提供以下三种数据结构,其底层实现以及优劣如下表所示
在这里插入图片描述

std::unordered_map底层实现为哈希表,std::map 和std::multimap的底层实现是红黑树,同理,std::map 和std::multimap 的key也是有序的

使用集合解决哈希问题时,优先使用unordered_set,因为查询和增删效率最优

如果需要集合是有序的,那么就用set,如果要求不仅有序还要有重复数据的话,那么就用multiset

map是key-value的数据结构,map中,对key有限制,对value没有限制,因为key的存储方式使用红黑树实现

虽然std::set、std::multiset 的底层实现是红黑树,不是哈希表,std::set、std::multiset 使用红黑树来索引和存储,不过给我们的使用方式,还是哈希法的使用方式,即key和value。所以使用这些数据结构来解决映射问题的方法,我们依然称之为哈希法,map也是相同的道理

遇到了快速判断一个元素是否出现在集合里,就是使用哈希法

优劣:哈希法牺牲了空间换取了时间,因为要使用额外的数组,set或者map来存放数据,才能实现快速的查找

2 有效的字母异位词

本道题可以感受到数组用来做哈希表带来的便利

在这里插入图片描述
数组其实就是一个简单哈希表
本题定义一个数组,记录字符串s里字符出现的次数
在这里插入图片描述
时间复杂度为 O ( n ) O(n) O(n),空间上因为定义是的一个常量大小的辅助数组,所以空间复杂度为 O ( 1 ) O(1) O(1)
伪代码:

(1)定义一个辅助数组hash[26],每个元素初始化为0,记录每个字符出现的次数
(2)遍历s字符串,每个字符出现+1
(3)遍历t字符串,每个字符出现-1
(4)遍历hash[26]数组,如果里面有不为0的元素,返回false,否则遍历完返回true

C++:

class Solution {
public:bool isAnagram(string s, string t) {int hash[26] = {0};// 并不需要记住字符a的ASCII,只要求出一个相对数值就可以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++){// 数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符if (hash[i] != 0) return false;}// 数组所有元素都为零0,说明字符串s和t是字母异位词return true;}
};

Python:

class Solution(object):def isAnagram(self, s, t):""":type s: str:type t: str:rtype: bool"""hash = [0] * 26for i in s:hash[ord(i) - ord('a')] += 1 # ord()返回ASCII值for i in t:hash[ord(i) - ord('a')] -= 1for i in range(26):if hash[i] != 0:return Falsereturn True

3 两个数组的交集

本题考虑什么时候用数组,什么时候用set
在这里插入图片描述
参考博客:C++常用语法——unordered_set
该题目特别说明:输出结果中的每个元素一定是唯一的,也就是说输出的结果的去重的, 同时可以不考虑输出结果的顺序
本题考虑用数组或者用set

使用数组来做哈希的题目,是因为题目限制了数值的大小,如果没有限制,就无法使用数组来做哈希表了。如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费

使用unordered_set 读写效率是最高的,并不需要对数据进行排序,本题不让数据重复,所以选择unordered_set
在这里插入图片描述
伪代码:

(1)创建一个存放结果的unordered_set
(2)将nums1转换为unordered_set
(3)遍历nums2,如果发现nums2里的元素在nums_set出现过,将元素插入存放结果的unordered_set
(4)返回result_set

用unordered_set
C++:

class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {unordered_set<int> result_set;// 存放结果, 用unordered_set是为了给结果去重unordered_set<int> nums_set(nums1.begin(), nums1.end());for (auto i : nums2){// 发现nums2的元素 在nums_set里又出现过if (nums_set.find(i) != nums_set.end()){result_set.insert(i);}}return vector<int>(result_set.begin(), result_set.end());}
};

时间复杂度: O ( m + n ) O(m+n) O(m+n)
空间复杂度: O ( n ) O(n) O(n)
Python:

class Solution(object):def intersection(self, nums1, nums2):return list(set(nums1) & set(nums2))

用数组

因为leetcode改了数据,增加了数值范围,所以本题可以用数组。使用数组来做哈希表,因为数组都是 1000以内的

C++:

class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {unordered_set<int> result_set;int hash[1010] = {0};for (auto i : nums1) // nums1中出现的字母在hash数组中做记录{hash[i] = 1;}for (auto i : nums2)// nums2中出现话,result记录{if (hash[i] == 1) result_set.insert(i);}return vector<int>(result_set.begin(), result_set.end());}
};

时间复杂度: O ( m + n ) O(m+n) O(m+n)
空间复杂度: O ( n ) O(n) O(n)
Python:

class Solution(object):def intersection(self, nums1, nums2):""":type nums1: List[int]:type nums2: List[int]:rtype: List[int]"""count1 = [0] * 1010count2 = [0] * 1010result = []for i in range(len(nums1)):count1[nums1[i]] += 1for j in range(len(nums2)):count2[nums2[j]] += 1for k in range(1010):if count1[k]*count2[k]>0:result.append(k)return result

4 快乐数

在这里插入图片描述
思路:
题目中说会无限循环,就是说求和的过程中,sum会重复出现

当遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法
这道题目使用哈希法,来判断这个sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止

C++:

class Solution {
public:int getSum(int n) {int sum = 0;while (n) {sum += (n % 10) * (n % 10);n /= 10;	}	return sum;}bool isHappy(int n) {unordered_set<int> set;while (1) {int sum = getSum(n);if (sum == 1) return true;if (set.find(sum) != set.end()){return false;}else {set.insert(sum);}n = sum;	}}
};

时间复杂度: O ( l o g n ) O(logn) O(logn)
空间复杂度: O ( l o g n ) O(logn) O(logn)
Python:

class Solution(object):def isHappy(self, n):""":type n: int:rtype: bool"""record = set()while True:n = self.get_sum(n)if n == 1:return Trueif n in record:return Falseelse:record.add(n)def get_sum(self, n):new_sum = 0while n:n, r = divmod(n, 10)new_sum += r ** 2return new_sum

5 两数之和

数组,set之后,使用map解决哈希问题
在这里插入图片描述

使用哈希法:当查询一个元素是否出现过,或者一个元素是否在集合里

本题要知道元素有无遍历过,还需要知道元素对应的下标,需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适

使用数组和set来做哈希法的局限

(1)数组的大小受限制,而且元素少,而哈希值太大会造成内存空间的浪费
(2)set是一个集合,里面放的元素只能是一个key,而这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x,y的下标。所以set也不能用

此时选择另一种数据结构:map

map是一种key value的存储结构,可以用key保存数值,用value再保存数值所在的下标。

在这里插入图片描述
这道题目中并不需要key有序,选择std::unordered_map效率更高
接下来明确两点:
(1)map用来做什么

map目的用来存放我们访问过的元素,因为遍历数组的时候,需要记录我们之前遍历过哪些元素和对应的下标,这样才能找到与当前元素相匹配的(也就是相加等于target)

(2)map中的key和value分别表示什么

给出一个元素,判断这个元素是否出现过,如果出现过,返回这个元素的下标。判断元素是否出现,这个元素就要作为key,所以数组中的元素作为key,有key对应的就是value,value用来存下标

在遍历数组的时候,只需要向map去查询是否有和目前遍历元素匹配的数值,如果有,就找到的匹配对,如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素
在这里插入图片描述
在这里插入图片描述
伪代码:

unordered_map<int, int> map;
for (i = 0; i < nums.size; i++)
{s = target - nums[i];iter = map.find(s);if (iter != map.end()) return {iter->value, i};map.insert(nums[i], i);
}
return {};

C++:

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {unordered_map<int, int> map; // map存放遍历过的元素// 遍历当前元素,并在map中寻找是否有匹配的keyfor (int i = 0; i < nums.size(); i++){int s = target - nums[i];auto iter = map.find(s);if (iter != map.end()) return { iter->second, i};// 如果没找到匹配对,就把访问过的元素和下标加入到map中map.insert(pair<int, int>(nums[i], i));}return {};}
};

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)

Python:

records = dict()# 遍历当前元素,并在map中寻找是否有匹配的keyfor index, value in enumerate(nums):if target - value in records:return [records[target - value], index]records[value] = index # 如果没找到匹配对,就把访问过的元素和下标加入到mapreturn []

本题有四个要点:
(1)为什么会想到用哈希表
查询元素有没有再出现,元素在不在这个集合里
(2)哈希表为什么用map
因为用数组和集合有局限,数组的大小受限制,而且元素少,而哈希值太大会造成内存空间的浪费。集合是里面放的元素只能是一个key,本题还要返回对应元素的下标
(3)本题map是用来存什么的
map是用来存放遍历过的元素
(4)map中的key和value用来存什么的
key用来存放元素,value用来存放元素对应的下标


鼓励坚持六天的自己😀😀😀

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

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

相关文章

【开题报告】基于SpringBoot的艾滋病科普平台的设计与实现

1.选题背景 艾滋病&#xff08;艾滋病毒感染与免疫缺陷综合征&#xff09;是一种严重的传染病&#xff0c;对人类的健康和社会稳定造成了极大的影响。全球范围内&#xff0c;艾滋病已经成为公共卫生领域的重大挑战之一。尽管在科学研究和医疗技术方面取得了一定进展&#xff0…

MT8390商显广告机主板_MTK联发科安卓主板方案开发

商显广告机采用MediaTek 联发科平台主板方案。安卓主板具有更高的性能、更丰富的接口、更多的存储空间以及更为便捷的网络连接方式&#xff0c;可以满足更为复杂的开发和应用需求使其应用领域更加多元化&#xff0c;被广泛应用于各行各业。 商显广告机主板基于联发科MT8390八核…

repmgr手动切换主从失败,报错‘DETAIL: local node last receive LSN‘

repmgr:5.4.0 pgsql: 14.2 OS:centos7.8刚搭建好的repmgr主从使用命令手动进行切换失败,日志如下 postgresdb02:~$ repmgr standby switchover NOTICE: executing switchover on node "db02" (ID: 2) NOTICE: local node "db02" (ID: 2) will be promoted…

智能AI系统ChatGPT网站系统源码+Midjourney绘画+支持DALL-E3文生图,支持最新GPT-4-Turbo模型

一、AI创作系统 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI…

一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么

一个页面从输入URL到加载显示完成经历了以下过程&#xff1a; DNS解析&#xff1a;浏览器会解析URL中的域名&#xff0c;将其转换为对应的IP地址。如果浏览器缓存中存在该域名的IP地址&#xff0c;则跳过DNS解析步骤。 建立TCP连接&#xff1a;通过解析得到的IP地址&#xff0…

Ubuntu18.04安装Ipopt-3.12.8流程

本文主要介绍在Ubuntu18.04中安装Ipopt库的流程&#xff0c;及过程报错的解决方法&#xff0c;已经有很多关于Ipopt安装的博客&#xff0c;但经过我的测试&#xff0c;很多都失效了&#xff0c;经过探索&#xff0c;找到可流畅的安装Ipopt的方法&#xff0c;总结成本篇博客。 …

使用typescript搭建express

使用typescript搭建express 开始 为这个项目创建一个新的目录&#xff0c;使用下面的命令初始化项目并创建一个包。 NPM init -y初始化后&#xff0c;让我们安装必要的包 npm i express dotenv cors helmet body-parser 在express中配置typescript npm i -D typescript typ…

C#多进程通信之共享内存方式

共享内存方式应该最简单易用的 直接上代码,下面列出了2种,一种是映射视图,一种是映射流,任选一种即可 服务端: MemoryMappedFile memoryAccessor MemoryMappedFile.CreateNew("ProcessCommunicationAccessor", 500, MemoryMappedFileAccess.ReadWrite);//创建共享…

WordPress批量上传文章和自动发布文章的方法

专业介绍&#xff1a;WordPress批量上传文章技术解析 在现代数字时代&#xff0c;内容创作是网络存在的驱动力之一。对于博客作者、新闻编辑和内容管理员而言&#xff0c;高效地批量上传文章至WordPress平台是提高工作效率的一个关键方面。WordPress作为最受欢迎的内容管理系统…

【C语言】递归详解

目录 1.前言2. 递归的定义3. 递归的限制条件4. 递归举例4.1 求n的阶乘4.1.1 分析和代码实现4.1.2 画图演示 4.2 顺序打印一个整数的每一位4.2.1 分析和代码实现4.2.2 画图推演 4.3 求第n个斐波那契数 5. 递归与迭代5.1 迭代求第n个斐波那契数 1.前言 这次博客内容是与递归有关&…

【数组】-Lc27-移除元素(快慢双指针)

写在前面 最近想复习一下数据结构与算法相关的内容&#xff0c;找一些题来做一做。如有更好思路&#xff0c;欢迎指正。 目录 写在前面一、场景描述二、具体步骤1.环境说明2.代码 写在后面 一、场景描述 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地移除所有数值等于…

迪文串口5使用查询方式发送数据

迪文屏串口5寄存器如下 发送数据我采用的不是中断&#xff0c;而是查询发送标志位实现的。 串口5不像串口2一样&#xff08;串口2可以位寻址&#xff0c;串口5不行&#xff09;&#xff0c;所以如果采用查询模式&#xff0c;需要判断寄存器的数据&#xff0c;我的写法比较简单…

Django高级之——Ajax、cookie与session

一 什么是Ajax AJAX&#xff08;Asynchronous Javascript And XML&#xff09;翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互&#xff0c;传输的数据为XML&#xff08;当然&#xff0c;传输的数据不只是XML,现在更多使用json数据&#xf…

apk和小程序渗透测试

apk和小程序渗透测试 文章目录 apk和小程序渗透测试小程序渗透测试apk和小程序的抓包安装证书apk渗透 小程序渗透测试 小程序的默认路径在 C:\Program Files (x86)\Tencent\WeChat\WeChatApp 使用UnpackMiniApp、wxappUnpacker工具完成逆向 先打开UnpackMiniApp.exe工具 选…

C++ 指针详解

目录 一、指针概述 指针的定义 指针的大小 指针的解引用 野指针 指针未初始化 指针越界访问 指针运算 二级指针 指针与数组 二、字符指针 三、指针数组 四、数组指针 函数指针 函数指针数组 指向函数指针数组的指针 回调函数 指针与数组 一维数组 字符数组…

pbootcms建站

pbootcms建站 一、下载pbootcms二、安装1、进入宝塔面在网站栏&#xff0c;新建站点&#xff0c;将该址里面文件全部清再将下载的pbootcms上传至该地址。 三、修改关联数据库1、在根目录下/config打开database.php照如下修改这里我使用mysqli数据库。修改并使用自已创建的数据库…

全网最新最全的自动化测试:python+pytest接口自动化-接口测试基础

接口定义 一般我们所说的接口即API&#xff0c;那什么又是API呢&#xff0c;百度给的定义如下&#xff1a; API&#xff08;Application Programming Interface&#xff0c;应用程序接口&#xff09;是一些预先定义的接口&#xff08;如函数、HTTP接口&#xff09;&#xff0c…

【Linux】服务器免密登陆

由于专业要求&#xff0c;我需要经常通过 VSCode、Terminal 等工具连接远程服务器开展工作。而每次连接都需要输入一次或多次密码无疑影响了工作体验。基于该背景&#xff0c;本文介绍了免密登陆远程服务器的方式。 1. 生成 id_rsa.pub 文件 根据自己的邮箱地址&#xff0c;利…

AIGC: 关于ChatGPT中Function Call的调用

Function Call 概念 关于 GPT 中API的function参数&#xff0c;提供了一些能力 这个函数调用是 Open AI 在2023年的6.13号发布的新能力根据它的官方描述, 函数调用能力可以让模型输出一个请求调用函数的消息其中包含所需调用函数的信息&#xff0c;以及调用函数时所需携带的参…

CMD批量添加防火墙端口

通过命令提示符窗口输入命令&#xff0c;添加防火墙允许端口。语法格式如下&#xff1a; netsh advfirewall firewall add rule name新端口 protocolTCP localport新端口 dirin actionallow,block 其中allow允许&#xff0c;block禁止以33088端口为例&#xff0c;用管理员身份…