「这是我参与2022首次更文挑战的第25天,活动详情查看:2022首次更文挑战」。
350. 两个数组的交集 II
题目描述
给你两个整数数组 nums1
和 nums2
,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。
示例 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 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000
进阶:
- 如果给定的数组已经排好序呢?你将如何优化你的算法?
- 如果
nums1
**的大小比nums2
小,哪种方法更优? - 如果
nums2
**的元素存储在磁盘上,内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?
暴力法
class Solution1
{
private:
vector<int> func(multiset<int> set1, multiset<int> set2, vector<int> nums)
{
// 记录最终得结果
multiset<int> mset;
// 遍历size较小的数组
for (int i = 0; i < nums.size(); i++)
{
// 判断set中是否存在元素 nums[i]
int n1 = set1.count(nums[i]);
int n2 = set2.count(nums[i]);
int n3 = mset.count(nums[i]);
// 如果在两个数组中都存在
if (n1 && n2)
{
// 判断记录的次数是否小于nums[i]在两个数组中出现的最小次数
if (n3 < (n1 < n2 ? n1 : n2))
{
mset.insert(nums[i]);
}
}
}
// 转换为 vector
vector<int> result(mset.begin(), mset.end());
return result;
}
public:
vector<int> intersect(vector<int> &nums1, vector<int> &nums2)
{
// 拷贝两个数组
multiset<int> set1(nums1.begin(), nums1.end());
multiset<int> set2(nums2.begin(), nums2.end());
// 判断哪个数组较小
if (nums1.size() <= nums2.size())
{
return func(set1, set2, nums1);
}
return func(set1, set2, nums2);
}
};
排序+双指针法
class Solution
{
public:
vector<int> intersect(vector<int> &nums1, vector<int> &nums2)
{
// 先对两个数组进行排序
sort(nums1.begin(), nums1.end());
sort(nums2.begin(), nums2.end());
int idx1 = 0;
int idx2 = 0;
vector<int> result;
// 遍历两个数组
while (idx1 < nums1.size() && idx2 < nums2.size())
{
// 数组1的元素小于数组2的元素,将索引前移
if (nums1[idx1] < nums2[idx2])
{
idx1++;
}
else if (nums1[idx1] == nums2[idx2])
{
// 记录结果
result.push_back(nums1[idx1++]);
idx2++;
}
else
{
// 数组2的元素较小,索引前移
idx2++;
}
}
return result;
}
};