哈希表 | 3 349. 两个数组的交集(set的使用)

本文记录的是刷题过程中的重要概念和笔记。如有侵权,请联系删除。

如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费!

349. 两个数组的交集

力扣题目链接(opens new window) https://leetcode.cn/problems/intersection-of-two-arrays/

题意:给定两个数组,编写一个函数来计算它们的交集。
在这里插入图片描述

说明: 输出结果中的每个元素一定是唯一的。 我们可以不考虑输出结果的顺序。

思路

主要要学会使用一种哈希数据结构:unordered_set

直接使用set 不仅占用空间比数组大,而且速度要比数组慢,set把数值映射到key上都要做hash计算的。在数据量大的情况,差距是很明显的。

C++

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

注意点:

  • for (int num : nums2)
  • nums_set.find(num) != nums_set.end()
  • result_set.insert(num);
  • unordered_set<int> nums_set(nums1.begin(), nums1.end());
  • == return vector<int>(result_set.begin(), result_set.end()); ==

补充:set使用

Set类似于数组,但是成员的值都是唯一的,没有重复的值。

Set 本身是一个构造函数,用来生成Set 数据结构。Set函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。

声明: unordered_set nums_set(nums1.begin(), nums1.end());

Set中的特殊值

Set 对象存储的值总是唯一的,所以需要判断两个值是否恒等。有几个特殊值需要特殊对待:

  • +0 与 -0 在存储判断唯一性的时候是恒等的,所以不重复,只能存在一个
  • undefined 与 undefined 是恒等的,所以不重复,只能存在一个
  • NaN 与 NaN 是不恒等的,但是在 Set 中认为NaN与NaN相等,所有只能存在一个,不重复。

Set实例对象的属性

  • size:返回Set实例的成员总数。

Set实例对象的方法

表 1 C++ set 容器常用成员方法
成员方法 功能

  • begin() 返回指向容器中第一个(注意,是已排好序的第一个)元素的双向迭代器。如果 set 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
  • end() 返回指向容器最后一个元素(注意,是已排好序的最后一个)所在位置后一个位置的双向迭代器,通常和 begin() 结合使用。如果 set 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
  • rbegin() 返回指向最后一个(注意,是已排好序的最后一个)元素的反向双向迭代器。如果 set 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。
  • rend() 返回指向第一个(注意,是已排好序的第一个)元素所在位置前一个位置的反向双向迭代器。如果 set 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。
  • cbegin() 和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的元素值。
  • cend() 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的元素值。
  • crbegin() 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的元素值。
  • crend() 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的元素值。
  • find(val) 在 set 容器中查找值为 val 的元素,如果成功找到,则返回指向该元素的双向迭代器;反之,则返回和 end() 方法一样的迭代器。另外,如果 set 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
  • lower_bound(val) 返回一个指向当前 set 容器中第一个大于或等于 val 的元素的双向迭代器。如果 set 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
  • upper_bound(val) 返回一个指向当前 set 容器中第一个大于 val 的元素的迭代器。如果 set 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
  • equal_range(val) 该方法返回一个 pair 对象(包含 2 个双向迭代器),其中 pair.first 和 lower_bound() 方法的返回值等价,pair.second 和 - upper_bound() 方法的返回值等价。也就是说,该方法将返回一个范围,该范围中包含的值为 val 的元素(set 容器中各个元素是唯一的,因此该范围最多包含一个元素)。
  • empty() 若容器为空,则返回 true;否则 false。
  • size() 返回当前 set 容器中存有元素的个数。
  • max_size() 返回 set 容器所能容纳元素的最大个数,不同的操作系统,其返回值亦不相同。
  • insert() 向 set 容器中插入元素。
  • erase() 删除 set 容器中存储的元素。
  • swap() 交换 2 个 set 容器中存储的所有元素。这意味着,操作的 2 个 set 容器的类型必须相同。
  • clear() 清空 set 容器中所有的元素,即令 set 容器的 size() 为 0。
  • emplace() 在当前 set 容器中的指定位置直接构造新元素。其效果和 insert() 一样,但效率更高。
  • emplace_hint() 在本质上和 emplace() 在 set 容器中构造新元素的方式是一样的,不同之处在于,使用者必须为该方法提供一个指示新元素生成位置的迭代器,并作为该方法的第一个参数。
  • count(val) 在当前 set 容器中,查找值为 val 的元素的个数,并返回。注意,由于 set 容器中各元素的值是唯一的,因此该函数的返回值最大为 1。

构造方法:

set和multiset的构造方法:
set<Key, Compare, Allocator> set_name;
multiset<Key, Compare, Allocator> multiset_name;
以上构造方法创建一个空的set或multiset对象,其中Key是存储的元素类型,Compare是用于元素比较的函数对象类型(默认为std::less),Allocator是用于内存分配的分配器类型(默认为std::allocator)。
unordered_set的构造方法:
unordered_set<Key, Hash, KeyEqual, Allocator> unordered_set_name;
以上构造方法创建一个空的unordered_set对象,其中Key是存储的元素类型,Hash是用于计算哈希值的函数对象类型(默认为std::hash),KeyEqual是用于比较元素相等性的函数对象类型(默认为std::equal_to),Allocator是用于内存分配的分配器类型(默认为std::allocator)。

常用方法:

插入元素:
void insert(const value_type& value);:将元素插入到容器中。
删除元素:
void erase(const value_type& value);:删除与指定值相等的元素。
iterator erase(iterator position);:删除指定位置的元素。

// 删除指定位置的元素
    auto it = my_set.find(30);
    if (it != my_set.end()) {
        my_set.erase(it);
    }

iterator erase(iterator first, iterator last);:删除指定范围内的元素。

// 删除指定范围内的元素
    auto first = my_set.begin();
    auto last = my_set.find(40);
    if (last != my_set.end()) {
        my_set.erase(first, last);
    }

查找元素:
iterator find(const value_type& value);:查找与指定值相等的元素,并返回指向该元素的迭代器,如果未找到则返回尾后迭代器。

// 查找元素
    auto set_it = my_set.find(20);
    if (set_it != my_set.end()) {}

size_type count(const value_type& value);:返回与指定值相等的元素的数量。
容器大小:
size_type size() const;:返回容器中元素的数量。
bool empty() const;:检查容器是否为空。
迭代器:
iterator begin();:返回指向容器第一个元素的迭代器。
iterator end();:返回指向容器末尾的迭代器。
注意:以上方法在set、multiset和unordered_set中都适用。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值