📅  最后修改于: 2023-12-03 15:21:33.769000             🧑  作者: Mango
本文将介绍 LeetCode 上的「两个数组的并集」问题,并提供 C++ 的解决方案。下面我们将逐步解析这个问题并提供可行的解决方案。
给定两个整数数组 nums1
和 nums2
,请编写一个函数来计算它们的交集。
输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2]
输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [9,4]
最直接的做法是使用哈希表存储 nums1
中的数字及其出现的次数,然后遍历 nums2
,如果数字在哈希表中出现过,则将其添加到答案并减小哈希表中该数字出现次数的值。
代码实现如下:
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_map<int, int> m;
vector<int> res;
for (auto num : nums1) {
m[num]++;
}
for (auto num : nums2) {
if (m[num] > 0) {
res.push_back(num);
m[num]--;
}
}
return res;
}
};
复杂度分析
nums1
和 nums2
的长度。使用两个哈希集合分别存储两个数组,每个集合的插入操作的时间复杂度为 $O(n)$,其中 $n$ 为对应数组的长度。而哈希集合的查询操作的时间复杂度最坏为 $O(n)$,因此总时间复杂度为 $O(n + m)$。nums1
和 nums2
的长度。空间复杂度主要取决于两个哈希集合。对两个数组进行排序,然后使用双指针的方法找到它们的公共元素。
具体来说,首先对两个数组进行排序,然后使用两个指针遍历两个数组。初始时,两个指针分别指向两个数组的头部,并依次将两个指针指向的数字进行比较,如果相等,则将该数字添加到答案并将两个指针同时右移;如果不相等,则将指向较小数字的指针右移一位。
代码实现如下:
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
sort(nums1.begin(), nums1.end());
sort(nums2.begin(), nums2.end());
int i = 0, j = 0;
vector<int> res;
while (i < nums1.size() && j < nums2.size()) {
if (nums1[i] < nums2[j]) {
i++;
} else if (nums1[i] > nums2[j]) {
j++;
} else {
if (res.empty() || res.back() != nums1[i]) {
res.push_back(nums1[i]);
}
i++;
j++;
}
}
return res;
}
};
复杂度分析
nums1
和 nums2
的长度。对两个数组排序的时间复杂度分别为 $O(n\log n)$ 和 $O(m\log m)$,双指针寻找公共元素的时间复杂度为 $O(n + m)$,因此总时间复杂度为 $O(n\log n + m\log m)$。nums1
和 nums2
的长度。为返回值创建一个数组 res
,数组长度为 $\min(n, m)$,因此空间复杂度为 $O(\min(n, m))$。不过我们可以忽略创建数组的空间,因为存储答案不属于算法的空间复杂度。如果在使用排序的语言中使用语言内置的排序函数,则不需要考虑排序的空间复杂度。本文详细介绍了 LeetCode 上的「两个数组的并集」问题,并提供了哈希表和排序 + 双指针两种解决方案。较为复杂的哈希表解法相对简单,且有较好的时空复杂度。而排序 + 双指针方法则更为优秀,时间复杂度与相对更低的空间复杂度使其成为更优秀的算法实现。
关于其他问题和更多解法,请参见LeetCode。