本文记录的是刷题过程中的重要概念和笔记。如有侵权,请联系删除。
如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费!
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中都适用。