给定两个数组,编写一个函数来计算它们的交集。
示例 1:
输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2,2]
示例 2:输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [4,9]
说明:输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。
我们可以不考虑输出结果的顺序。
1.暴力法
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
vector<int> ret;
for(vector<int>::iterator it1 = nums1.begin(); it1 != nums1.end(); it1++) {
for(vector<int>::iterator it2 = nums2.begin(); it2 != nums2.end(); it2++) {
if(*it1 == *it2) {
ret.push_back(*it1);
*it1 = -10086;
*it2 = -10085;
}
}
}
return ret;
}
};
2.具有记忆的双指针法
class Solution {
public:
static bool cmp(const int&a,const int &b)
{
return a<b;
}
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
if(nums1.empty()||nums2.empty())
return {};
sort(nums1.begin(),nums1.end(),cmp);
sort(nums2.begin(),nums2.end(),cmp);
if(nums1[0]>nums2[nums2.size()-1])
return {};
vector<int> res;
int i=0;//指向nums1的指针
int k=0;//指向nums2的指针
int j=0;//记忆上一次搜索位置
for(;i<nums1.size();i++)
{
while(k<nums2.size()&&nums1[i]!=nums2[k])//找到相同元素的nums2中的下标
k++;
if(k!=nums2.size())//找到相同元素
{
res.push_back(nums2[k]);
k++;
j=k;//记忆
}
else if(nums1[i]>nums2[k-1])//由于排序过,所以可以这样判断
break;
else k=j;//反之从上一次搜索位置开始
}
return res;
}
};
3.利用哈希表查找元素
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
if(nums1.size()>nums2.size()) swap(nums1,nums2);//用元素少的数组元素查找
map<int,int> a;
for(int i=0;i<nums2.size();i++)//初始化map
{
if(!a.count(nums2[i]))
a.insert(map<int,int>::value_type(nums2[i],1));
else a[nums2[i]]++;
}
vector<int> res;
for(int i=0;i<nums1.size();i++)
{
if(a.count(nums1[i]))
{
if(a[nums1[i]]!=0)
{
res.push_back(nums1[i]);
a[nums1[i]]--;
}
}
}
return res;
}
};
4.直接在数组上查找
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
vector<int> res;
vector<int>::iterator it;
for(int i=0;i<nums1.size();i++)
{
it=find(nums2.begin(),nums2.end(),nums1[i]);
if(it!=nums2.end())//查找到元素
{
res.push_back(*it);
nums2.erase(it);//删除元素
}
}
return res;
}
};