力扣第349题 两个数组的交集 不会set不会哈希? 一题教懂你

题目

349. 两个数组的交集

简单

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

示例 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 <= nums1.length, nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 1000

思路和解题方法

  • 首先,我们定义了两个 unordered_set<int> 类型的变量: result_setnums_set。其中, nums_set 用于存储 nums1 中的元素,并通过将 nums1 数组中的所有元素插入到集合中,实现了去除重复元素的功能。而 result_set 则用于存储交集的结果。
  • 接下来,我们遍历 nums2 数组中的每个元素 num。对于每个元素 num,我们使用 nums_set.find(num) 查找该元素是否在 nums_set 中出现过。如果找到了,则说明该元素也存在于 nums1 中,属于交集的一部分,因此将其添加到 result_set 集合中。
  • 最后,我们使用 vector<int>(result_set.begin(), result_set.end())result_set 集合转换为一个 vector,并作为函数返回值,完成了求交集的操作。

复杂度

        时间复杂度:

                O(m+n)

其中 m 和 n 分别是 nums1 和 nums2 的长度。遍历 nums1 并将其插入到哈希表中的时间复杂度是 O(m),遍历 nums2 查找交集并插入结果集的时间复杂度是 O(n)。总体来说,时间复杂度为 O(m + n)。

        空间复杂度

                O(m)

其中 m 是 nums1 的长度。使用一个额外的哈希表来存储 nums1 中的元素,最坏情况下需要存储全部元素。因此,空间复杂度为 O(m)。

c++ 代码

 ​
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result_set;              // 存储交集结果的哈希集合
        unordered_set<int> nums_set(nums1.begin(), nums1.end());  // 将 nums1 中的元素存储到哈希集合中

        for (int num : nums2) {                     // 遍历 nums2 数组中的每个元素
            if (nums_set.find(num) != nums_set.end()) {       // 若该元素在 nums_set 中存在
                result_set.insert(num);                         // 将其插入结果集中
            }
        }

        return vector<int>(result_set.begin(), result_set.end());   // 将结果集转换为 vector 返回
    }
};

set容器和哈希

C++ 标准库提供了多种容器供选择。其中包括 set 容器和哈希表(unordered_set)。下面我们来解释一下它们的特点和用法。

1. Set 容器:

  • set 是一个有序集合容器,它维护了一组唯一的元素。这意味着在 set 中不能存在重复的元素,并且元素按照自然顺序进行排序。如果需要自定义排序,可以通过提供比较函数或函数对象来实现。
  • set 提供了高效地插入、删除和查找操作,其时间复杂度为 O(log n)。这是因为 set 内部使用了平衡二叉搜索树(通常是红黑树)来组织元素。由于元素是有序的,set 还支持一些有关范围查找的操作,例如查找给定范围内的所有元素。
  • 使用 set 容器的一些常见用途包括去除重复元素、排序和查找唯一元素。

2. 哈希表(unordered_set):

  • 哈希表(也称为散列表)是一种使用哈希函数将键映射到存储位置的数据结构。在 C++ 的标准库中,哈希表对应的容器是 unordered_set
  • unordered_set 是一个无序集合容器,其中的元素是唯一的。它使用哈希函数来确定元素的存储位置,因此插入、删除和查找操作的时间复杂度通常是常数时间 O(1)。然而,在最坏的情况下(例如哈希函数导致大量冲突),时间复杂度可能会变为 O(n)。
  • set 不同,unordered_set 不维护元素的顺序。这意味着在遍历时,并不能保证元素的顺序和插入的顺序一致。如果需要有序的集合,应该使用 set 而不是 unordered_set
  • 由于哈希表的特性,unordered_set 在查找和去重方面非常高效。它适用于不需要有序元素的场景,例如统计元素出现次数、判断元素是否存在等。
  • 需要注意的是,unordered_set 对象的元素类型必须支持哈希函数和相等运算符,或者自定义一个哈希函数和相等运算符以供使用。
  • 总结起来,set 是有序的集合容器,适用于排序、去重及范围查找等场景;unordered_set 是无序的集合容器,适用于高效的插入、删除和查找操作。选择使用哪个容器要根据具体的需求和性能要求来决定。

额外知识

unordered_map

unordered_map 是 C++ 标准库中的一个哈希表容器,用于存储键值对。它提供了高效的插入、删除和查找操作,并且这些操作的时间复杂度通常是常数时间 O(1)。以下是关于 unordered_map 的一些重要特点和用法:

  1. 存储键值对unordered_map 存储了一系列键值对,每个键都唯一。键(key)和值(value)可以是任意类型的,只要满足特定要求(例如支持哈希函数和相等比较运算符)。插入新的键值对时,可以使用下标运算符 []insert() 函数。

  2. 哈希函数unordered_map 使用哈希函数将键映射到内部存储位置。哈希函数负责计算键的哈希值,然后将其转换为对应的存储索引。C++ 标准库已经提供了对许多常见类型的默认哈希函数,但你也可以自定义哈希函数来适应特定的键类型。

  3. 冲突解决: 在哈希表中,冲突指的是两个或多个键被映射到相同的存储索引。unordered_map 使用拉链法来解决冲突。具体来说,每个存储索引都是一个链表,同一索引上的键值对通过链表连接在一起。当出现冲突时,新的键值对将插入到对应索引的链表中。

  4. 高效的操作unordered_map 提供了高效的操作,包括插入、删除和查找。这些操作的平均时间复杂度是常数时间 O(1),但在最坏情况下(例如存在大量冲突),时间复杂度可能会退化为线性时间 O(n)。因此,选择合适的哈希函数和控制冲突是确保性能的关键。

  5. 迭代器和范围遍历: 可以使用迭代器对 unordered_map 中的键值对进行遍历。迭代器提供了访问键和值的方法,可以通过递增迭代器来依次访问每个键值对。此外,unordered_map 也支持范围遍历,通过结合 C++11 的范围循环语法,可以方便地遍历所有键值对。

unordered_map 是很常用的容器之一,适用于需要根据键快速查找对应值的场景。它具有高效的操作,且允许自定义键类型和哈希函数。然而,需要注意的是,unordered_map 不保持键的插入顺序。如果需要有序的容器,应该考虑使用 map 容器。

unordered_set

unordered_set 是 C++ 标准库中的一个哈希表容器,用于存储唯一的元素。它提供了高效的插入、删除和查找操作,并且这些操作的时间复杂度通常是常数时间 O(1)。以下是一些关于 unordered_set 的重要特点和用法:

  1. 存储唯一元素unordered_set 存储了一组唯一的元素,每个元素都是独一无二的。它使用哈希函数将元素映射到内部存储位置,并使用拉链法解决冲突。在插入新元素时,会根据哈希函数计算元素的哈希值,然后将其插入到对应的存储索引位置。

  2. 哈希函数unordered_set 使用哈希函数将元素映射到内部存储位置。哈希函数负责计算元素的哈希值,然后将其转换为对应的存储索引。C++ 标准库已经提供了对许多常见类型的默认哈希函数,但你也可以自定义哈希函数来适应特定的元素类型。

  3. 冲突解决: 在哈希表中,冲突指的是两个或多个元素被映射到相同的存储索引。unordered_set 使用拉链法来解决冲突。具体来说,每个存储索引都是一个链表,同一索引上的元素通过链表连接在一起。当出现冲突时,新的元素将插入到对应索引的链表中。

  4. 高效的操作unordered_set 提供了高效的插入、删除和查找操作。这些操作的平均时间复杂度是常数时间 O(1),但在最坏情况下(例如存在大量冲突),时间复杂度可能会退化为线性时间 O(n)。因此,选择合适的哈希函数和控制冲突是确保性能的关键。

  5. 迭代器和范围遍历: 可以使用迭代器对 unordered_set 中的元素进行遍历。迭代器提供了访问元素的方法,可以通过递增迭代器来依次访问每个元素。此外,unordered_set 也支持范围遍历,通过结合 C++11 的范围循环语法,可以方便地遍历所有元素。

unordered_set 是一个常用的容器,适用于需要高效去重和快速查找元素的场景。它具有高效的操作,且允许自定义元素类型和哈希函数。然而,需要注意的是,unordered_set 不保持元素的插入顺序。如果需要有序的容器,应该考虑使用 set 容器。

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦  >人<  。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值