代码随想录day7|哈希表,有效字母异位,两个数组的交集

哈希表理论基础

我们知道数组其实就是一张哈希表,那么哈希表一般可以解决什么问题?
一般哈希表都是用来快速判断一个元素是否出现在集合里

例如要查询一个名字是否在这所学校里。
要枚举的话时间复杂度是O(n),但如果使用哈希表的话, 只需要O(1)就可以做到。
我们只需要初始化把这所学校里学生的名字都存在哈希表里,在查询的时候通过索引直接就可以知道这位同学在不在这所学校里了。

什么是哈希函数

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

常见的三种哈希结构

当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构。

数组
set (集合)
map(映射)

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

std::unordered_map 底层实现为哈希表
std::map 和std::multimap 的底层实现是红黑树。
同理,std::map 和std::multimap 的key也是有序的(这个问题也经常作为面试题,考察对语言容器底层的理解)。

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

小总结

如果在做面试题目的时候遇到需要判断一个元素是否出现过的场景也应该第一时间想到哈希法!

242.有效的字母异位词

题目链接:242.有效的字母异位词
题目描述:给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

示例 1: 输入: s = "anagram", t = "nagaram" 输出: true

示例 2: 输入: s = "rat", t = "car" 输出: false

说明: 你可以假设字符串只包含小写字母。

思路

数组其实就是一个简单的哈希表,来记录字符串s里面出现的次数,而对于哈希表set一般在数值很大使用,map一般在有k值或val值时使用。

1、那么定义一个record数组记录s字符串出现的次数 
2、把字符串映射到哈希表(数组)的索引下标上 0-25
3、遍历字符串s( s[i] - ‘a’ 所在的元素做+1 操作即可)
4、遍历字符串t,检查是否有相同字符,有则减去对应的下标值

代码如下

class Solution {
public:
    bool isAnagram(string s, string t){
 		int record[26];
		 for(i = 0; i < s.size(); i++){//遍历s并记录字符串出现的字母数 
		 	record[s[i] - 'a']++;//其实就是字符串的字母到a(为0)的一个映射 
		 }   	
		 for(i = 0;i < t.size(); i++){
		 	record[s[i] - 'a']++;//对应t字符串出现的字母次数 减去对应下标值 
		 }
		 for(i = 0; i < 26; i++){
		 	if(record != 0){
		 		return false;//检查一遍哈希表,如果有的元素不为0,则出错 
			 }
		 } 
		 return true;//record数组所有元素都为零0,说明字符串s和t是字母异位词 
	}
}

349. 两个数组的交集

题目链接:349. 两个数组的交集
题目描述:给定两个数组,编写一个函数来计算它们的交集。

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

思路

要注意,使用数组来做哈希的题目,是因为题目都限制了数值的大小。而这道题目没有限制数值的大小,就无法使用数组来做哈希表了。

而且如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费。
此时就要使用另一种结构体了,set。那么要使用哪一种呢? |答:

std::unordered_set的底层实现是哈希表, 使用unordered_set 读写效率是最高的,并不需要
对数据进行排序,而且还不要让数据重复,所以选择unordered_set。

把第一个数组(nums1)转化为哈希表,然后我们遍历numbers2,第二个数组的每一个元素我们再去哈希表里去查是否出现过,如果出现过就放进result数组(集合去重)里。

代码如下

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());//即nums1转化为哈希表
        for(i = 0, i < nums2.size(),i++){//对数组2进行遍历操作
            if(nums_set.find(num) != nums_set.end()){//如果`发现nums2的元素 在nums_set里又出现过,直接放进result集合里`
             result_set.insert(num);           
}
}
    return vector(`result_set.begin(), result_set.end());//因为最后返回是数组形式,所以要把set转换为vector--即`vector<int>(result_set.begin(), result_set.end())`
}
}
posted @   认真小l  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示