题目
给定两个数组,编写一个函数来计算它们的交集。
方法一:排序+双指针
思路:
先将两个数组进行排序
两个指针分别指向数组下标,从左边第一个元素开始
1)所指的元素相同,放进vector里,注意vector的插入元素是 push_back(), set的才是insert,
注意:此时两个指针同时都要往后移动
2)所指的元素不相同,小的往后移,大的不动(它倒要看看后面还有没有我的交集)
直至 其中有一个数组遍历完了,即满足a<nums1.size()&&b<nums2.size()
代码:
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
sort(nums1.begin(),nums1.end());
sort(nums2.begin(),nums2.end());
int length1=nums1.size();
int length2=nums2.size();
vector<int> vec;
int a = 0,b = 0;
while(a<nums1.size()&&b<nums2.size()){
if(nums1[a]>nums2[b]){
b++;
}
else if(nums1[a]<nums2[b]){
a++;
}
else{
vec.push_back(nums1[a]);
a++;
b++;
}
}
return vec;
}
};
问题:
如果 nums1 的大小比 nums2 小很多,即如果 nums2 的元素存储在磁盘上,而内存是有限的,我们不能一次加载所有的元素到内存中,而我们排序需要把nums2从磁盘调入内存,这很花时间。那该怎么办呢?
方法二:map
思路
使用 unordered_map<int >
键值对
- 选取短的那一个数组,记录数字——他出现的次数
- 对于长的那个数组,我只需要看这个数字在短数组中出现没有
出现:放进vector,并且该数字对应出现的次数 - 1,若最后减到0,正好!因为需要元素在两个数组中出现次数的最小值一致,长数组中就算还有也不能算作交集
未出现:就说明不是交集
推荐这个方法,num2 只关系到查询操作,因此每次读取num2中的一部分数据,并进行处理即可,不需要排序
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
if(nums1.size()>nums2.size()){
intersect(nums2,nums1);
}
unordered_map<int,int> map;
for(int num1:nums1){
map[num1]++;
}
vector<int> vec;
for(int num2:nums2){
if(map[num2]){
vec.push_back(num2);
map[num2]--;
}
}
return vec;
}
};
彩蛋 bonus: :map中的count()方法返回值是一个整数,1表示有这个元素,0表示没有这个元素。
//没有1这个元素
maps.count(1)==0
//等价于
maps.find(1)==maps.end()
//有1这个元素
maps.count(1)==1
//等价于
maps.find(1)!=maps.end()