LeetCode 350. Intersection of Two Arrays 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 <= 10000 <= nums1[i], nums2[i] <= 1000
进阶:
- 如果给定的数组已经排好序呢?你将如何优化你的算法?
- 如果
nums1**的大小比nums2小,哪种方法更优? - 如果
nums2**的元素存储在磁盘上,内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?
算法
(哈希表) O(n+m)
首先先将nums1存入哈希表中,注意这里要用unordered_multiset,而不是unordered_set,因为数组中含有重复元素。
然后遍历nums2,对于每个数 x,如果 x 出现在哈希表中,则将 x 输出,且从哈希表中删除一个 x。
时间复杂度分析:
假设两个数组的长度分别是 n,m。将nums1存入哈希表的计算量是 O(n),遍历nums2的计算量是 O(m),所以总时间复杂度是 O(n+m)。
思考题:
如果给定的数组已经排好序,你可以怎样优化你的算法 ?
答:可以用双指针扫描。这样可以把空间复杂度降为 O(1),但时间复杂度还是 O(n);
如果数组nums1的长度小于数组nums2的长度,哪种算法更好?
答:可以把nums1存入哈希表,然后遍历nums2。这样可以使用更少的内存,但时空复杂度仍是 O(n);
如果数组nums2存储在硬盘上,然而内存是有限的,你不能将整个数组都读入内存,该怎么做?
答:如果nums1可以存入内存,则可以将nums1存入哈希表,然后分块将nums2读入内存,进行查找;如果两个数组都不能存入内存,可以先将两个数组分别排序,比如可以用外排序,然后用类似于双指针扫描的方法,将两个数组分块读入内存,进行查找。
C++ 代码
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
unordered_multiset<int> S;
vector<int> res;
for (int x : nums1) S.insert(x);
for (int x : nums2)
if (S.count(x))
{
res.push_back(x);
S.erase(S.find(x));
}
return res;
}
};