day6: 哈希表 - 判断元素是否在集合里

本文介绍了哈希表的基本概念,如何利用哈希表快速判断元素是否在集合中,以及在LeetCode题目中的应用实例,如判断字母异位词和求两个数组的交集。作者强调了哈希法的空间时间权衡,以及选择数组、set和map作为哈希结构的不同场景。
摘要由CSDN通过智能技术生成

哈希表 Hash table

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

  • 数组就是一张哈希表

  • 哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素

哈希表能解决什么问题?
  • 🍃 一般哈希表都是用来快速判断一个元素是否出现集合里

  • 比如:要查询一个名字是否在这所学校里,用哈希表只需要O(1)

做法:

  • 我们只需要初始化把这所学校里学生的名字都存在哈希表里,在查询的时候通过索引直接就可以知道这位同学在不在这所学校里了。

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

常见的三种哈希结构:
  1. 数组

  2. set 集合

  3. map 映射

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

  2. 但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。

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

242.有效的字母异位词 : Array

建议: 这道题目,大家可以感受到 数组 用来做哈希表 给我们带来的遍历之处。

题目

. - 力扣(LeetCode)

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

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

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

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

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

思路
  1. 遇到哈希表,去想最常用的三种结构:

    1. 数组:哈希值较小,范围可控 (能用数组尽量用数组,速度比较快)

    2. set :如果数值大,用set

    3. map:如果key对应有value,就用map

  2. 题目中说只有小写字母:26个字母

    1. 所以创建一个数组:hash[26]

    2. 遍历的时候,把所有字母出现的频率,就统计到了hash[26]的数组里

    3. 遍历第一个string时,在数组上hash[ ]++

    4. 遍历第二个string时,在同一个hash[]上--

    5. 如果最终这个hash[]为0,则说明两个字符串包含的字母数量一样(妙啊)

伪代码
int hash[26]; // default = 0
​
for(i=0; i<s.size(); i++){
  hash[s[i] - 'a']++; // 不需要记忆a的ASCII。使用'-a'直接就把a对应成hash[0]
}
​
for(i=0; i<t,size(); i++){
  hash[t[i] - 'a']--;
}
​
for (i=0; i<26; i++){
  if (hash[i] != 0):
    return false;
}

349. 两个数组的交集: Set

建议:

本题就开始考虑 什么时候用set 什么时候用数组,本题其实是使用set的好题,但是后来力扣改了题目描述和 测试用例,添加了 0 <= nums1[i], nums2[i] <= 1000 条件,所以使用数组也可以了,不过建议大家忽略这个条件。 尝试去使用set。

题目

. - 力扣(LeetCode)

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

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

示例 2:

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

思路
  1. 哈希表主要用来:判断一个元素是否出现在集合里

  2. 如果数据量很大,就用set

  3. 这道题中: 把nums1放到hash表里

  4. 然后再用nums2,遍历每一个元素去查询hash表

  5. 如果查到了,就把交集结果存放在Result里

用哪个set?

  1. set

  2. unorderd_set: 可以理解为可以无限存放的数组 (效率最高,我们用这个)

伪代码
// set
unordered_set result;
unordered_set nums_set(nums1); // 把nums1放入hash表中。这里nums_set是哈希表
​
for(i=0; i<nums2.size; i++){
  if (nums_set.find(nums2[i]) != nums_set.end()) { // 遍历查找nums2里的元素,是否和nums1里相同
      result.insert(nums2[i]);  // 把相同的放到Result里
  }
}  
return vector(result);
​
​
​
// array
unordered_set result; // 这个自动去重,所以我们还用这个
int hash[1005] = {0};
​
for(i=0; i<nums1.size; i++){
  hash[nums1[i]] = 1; // 把nums1的元素,在hash对应的数组中都设为1
}
​
for(i=0; i<nums2.size; i++){
  if(hash(nums2[i] == 1)){
    result.insert(nums2[i]);
  } 
}
return vector(result);
​

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值