Leetcode刷题 由浅入深之哈希表——349. 两个数组的交集
目录
(一)数组交集的C++实现
写法一(哈希暴力搜索)
写法二(哈希集合搜索)
(二)复杂度分析
时间复杂度
空间复杂度
(三)总结
【题目链接】349.两个数组的交集 - 力扣(LeetCode)
给定两个数组
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
(一)数组交集的C++实现
哈希表:对元素的值进行哈希映射(哈希函数),映射到对应下标位置。也就是已知一个值,经过哈希函数可以直接计算在哈希表中的存储位置。
哈希表的特点:元素值不重复,下标可以直接访问元素。
哈希表的作用:使用哈希表可以快速(直接根据值和哈希函数计算下标并访问)判断元素是否在表里,时间复杂度为。
写法一(哈希暴力搜索)
解题思路:
双重遍历实现比较,并将交集结果存入哈希表中。返回时,需要将哈希表转化为整型数组。
(借助哈希表就不需要再考虑重复插入的问题)
class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {set<int> hashlist; //哈希表的定义for(auto i : nums1){for(auto j : nums2){if(i == j)hashlist.insert(i); //哈希表的插入操作}}return vector<int> (hashlist.begin(), hashlist.end()); //返回整个哈希表构成的数组}
};
写法二(哈希集合搜索)
解题思路:
借助数学中寻找集合交集的思想,可以先将一个数组nums1变成具有集合特点的数组存储(也就是存储在一个哈希表中)。接着,可以遍历另一个数组nums2,如果元素在哈希表中,则将该值添加到交集数组中并在哈希表中删除;如果不在,则不需要进行任何操作。
这种办法时间复杂度更低,不需要遍历完两个数组的所有元素。
class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {set<int> hashlist; //定义整形哈希表vector<int> result; //定义整形数组(存储交集结果)for(auto i : nums1)hashlist.insert(i);for(auto j : nums2)if(hashlist.find(j) != hashlist.end()){ //不为hashlist.end()说明哈希表hashlist中有j这个值result.push_back(j); //写进数组hashlist.erase(j); //删除哈希表中的j这个值}return result;}
};
(二)复杂度分析
时间复杂度
(1)写法一:两层嵌套循环,假设nums1
的长度为m
,nums2
的长度为n
,那么比较的次数为m * n
。set
的插入操作平均时间复杂度是,其中
k
是set
中元素的数量。在最坏情况下,插入操作的总时间复杂度为 。因此,总的时间复杂度为
。
(2)写法二:第一个循环插入操作平均时间复杂度是,插入
m
个元素的总时间复杂度为。第二个循环遍历
nums2
,对于nums2
中的每个元素,执行查找操作和可能的删除操作,查找和删除操作的平均时间复杂度都是,因此第二个循环的总时间复杂度为
。所以,总的时间复杂度为
。
空间复杂度
(1)写法一:set
用来存储交集元素,在最坏情况下,交集元素的数量可能达到min(m, n)
,因此set
所占用的空间为;返回的
vector
也需要。所以,总的空间复杂度为
。
(2)写法二:set
用来存储nums1
中的元素,在最坏情况下,需要的空间。
result
数组用来存储交集元素,在最坏情况下,交集元素的数量可能达到min(m, n)
,因此result
数组需要的空间。所以,总的空间复杂度为
。
(三)总结
(1)哈希表可以快速判断元素是否在表里,相比于遍历搜索时间复杂度会更低。
(2)解题时多找一下数学规律。
学习中,诚挚希望有心者指正和交流,经验或者方法都可。