给定两个数组,写一个方法来计算它们的交集。
例如:
给定 nums1 = [1, 2, 2, 1]
, nums2 = [2, 2]
, 返回 [2, 2]
.
注意:
- 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。
- 我们可以不考虑输出结果的顺序。
跟进:
- 如果给定的数组已经排好序呢?你将如何优化你的算法?
- 如果 nums1 的大小比 nums2 小很多,哪种方法更优?
- 如果nums2的元素存储在磁盘上,内存是有限的,你不能一次加载所有的元素到内存中,你该怎么办?
思路:先排序,使用两个下标。如果数据过大不能一次性载入内存,有两种备选的处理方案,第一种是使用外部排序,依次载入比较,第二种是依次读入nums2,然后建立一个map,存贮nums2里面的数值和出现次数之间的关系,nums1,也做同样的处理,然后比较两个map
方法1:排序
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
vector<int> re;
if(nums1.empty() || nums2.empty())
return re;
sort(nums1.begin(), nums1.end());
sort(nums2.begin(), nums2.end());
int i=0, j=0;
while(i<nums1.size() and j< nums2.size()){
if(nums1[i]==nums2[j]){
re.push_back(nums1[i]);
i++;
j++;
}
else if(nums1[i]>nums2[j])
j++;
else
i++;
}
return re;
}
};
方法2:map
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
vector<int> re;
if(nums1.empty() || nums2.empty())
return re;
map<int, int> nums1map;
map<int, int> nums2map;
int i, j;
for(i=0;i<nums1.size();++i){
if(nums1map.count(nums1[i]))//说明存在这个数,加1
nums1map[nums1[i]]++;
else
nums1map[nums1[i]]=1;
}
for(j=0;j<nums2.size();++j){
if(nums2map.count(nums2[j]))//说明存在这个数,加1
nums2map[nums2[j]]++;
else
nums2map[nums2[j]]=1;
}
map<int, int>::iterator iter1=nums1map.begin();
map<int, int>::iterator iter2=nums2map.begin();
int minTimes=0, minkey;
while(iter1!=nums1map.end() and iter2!=nums2map.end()){
if(iter1->first==iter2->first){
minkey = (iter1->second < iter2->second)? iter1->first:iter2->first;
minTimes = (iter1->second < iter2->second)? iter1->second:iter2->second;
for(i=0;i<minTimes;++i)
re.push_back(minkey);
iter1++;
iter2++;
}
else if(iter1->first > iter2->first)
iter2++;
else
iter1++;
}
return re;
}
};