原题传送门
给定两个数组 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
对于给你一个元素,去判断在这个集合里是否出现过,这种题型,都应该第一时间想到哈希表,因为其实最搞笑的,接着既然是求解集合相关的问题,那就想到set,但是有关set的哈希结构有三种
| 集合 | 底层实现 | 是否有序 | 是否可重复 | 数值可否更改 | 查询效率 | 增删效率 |
|---|---|---|---|---|---|---|
| std::set | 红黑树 | 有序 | 否 | 否 | O(nlogn) | O(nlogn) |
| std::multiset | 红黑树 | 有序 | 是 | 否 | O(nlogn) | O(nlogn) |
| std::unordered_set | 哈希表 | 无序 | 是 | 否 | O(1) | O(1) |
set和multiset底层实现都是红黑树,unordered_set的底层实现是哈希表, 使用unordered_set 读写效率是最高的,并不需要对数据进行排序,而且还不要让数据重复,所以选择unordered_set,具体的详解如何选择哈希结构我在一文带你快速入门【哈希表】中有详解介绍过,如果不太清楚的小伙伴可以再去看看🏃

class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> result;
unordered_set<int> num(nums1.begin(),nums1.end()); //把nums1中数放入num集合
//遍历nums2数组,与num集合做比较
for(int i : nums2)
{
if(num.find(i) != num.end())
//没有到num的结尾就发现了异常情况
result.insert(i); //将交集元素放入result集合
}
//最后以一个vector容器的形式返回
return vector<int>(result.begin(),result.end());
}
};
此题的提交结果
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> result;
int hash[1004]{}; //采取数组存储
for(int i : nums1)
hash[i] = 1;
for(int j : nums2)
if(hash[j] == 1)
result.insert(j);
return vector<int>(result.begin(),result.end());
}
};
这是数组解法的通过效率,可以看出空间复杂度低了许多

由于动画太快了,因此我一步步分开细讲🔍
首先就是初始化时的样子

当两个值相等时,此数就为待插元素,就判断若还没到达结尾或者此数是否与上一个放入结果集中的数一样,如果都不符合,就讲此数放入结果集,然后两个指针后移,此时4 < 5,故index2后移

当碰到两个数不一样时,就判断是n1大还是n2大,比较完后较小数字的指针后移一位

此时5 < 8比较小,index1后移

。。。
遍历到此处时,由于两数相同,既没有到结果集末尾,上一个结果集中的数又不是9,因此将9放入结果集中

最后,当其中任意一指针超过当前数组长度时,便退出循环,返回结果集

以下是C++代码展示
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
//对两个数组进行排序
sort(nums1.begin(),nums1.end());
sort(nums2.begin(),nums2.end());
int index1 = 0,index2 = 0; //指向两个数组的指针
int l1 = nums1.size();
int l2 = nums2.size(); //获取两数组的长度
vector<int> result;
while(index1 < l1 && index2 < l2)
{ //index1、index2从0开始,因此不能遍历到l1和l2,否则会造成数组越界
int n1 = nums1[index1];
int n2 = nums2[index2];
if(n1 == n2){
if(!result.size() || n1 != result.back()){
//若还没到结果集结尾或者与上一个插入的容器中的值不同
result.push_back(n1);
}
index1++;
index2++; //双指针的共同后移
}else if(n1 < n2){
index1++;
}else{
index2++;
}
}
return result;
}
};
本题的通过效率

看完了此题的三种解法后,你是否又多了几种解题的思路呢,本题是哈希表章节中比较经典的题目,虽然并不是很难,但是想要有一个最优解却不易,以下也是哈希表相关的例题,大家在学习了哈希表的基础知识后多去刷刷题,对知识的理解会更加深刻,关注我,后续会有更精彩的题解奉上💥
1.两数之和
15. 三数之和
18. 四数之和
202. 快乐数
242.有效的字母异位词
以下是我开创的社区,感兴趣的小伙伴们可以加入进来一起交流学习,解决编程的难题
我的社区:🔥烈火神盾🔥