这是我参与11月更文挑战的第 13 天,活动详情查看:2021最后一次更文挑战
前言
在Javascript中,数组是一种常见的数据结构。数组拥有length属性和push, pop, slice等方法,在书写代码中经常会使用到,代表了一组数据的集合。
下面的题目是求两个数组的交集,需要注意的是,题目中给出的数组,其元素是可以有重复的。此外,如果是求两个数组的并集或补集呢,代码会有什么不同之处?💡
题目
给定两个数组,编写一个函数来计算它们的交集。
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]
说明:
-
输出结果中每个元素出现的次数,应与元素在两个数组中出现次数的最小值一致。
-
我们可以不考虑输出结果的顺序。
思考
最直观的想法,是使用两个for循环去遍历这两个数组,如果有相同元素,则添加到返回值的数组中去。但是这样子,代码的时间复杂度高达O(n^2),显然不够优雅...
我们可以借助哈希表,记录其中一个数组中每个元素出现的次数,然后遍历第二个数组,判断数组元素是否存在于哈希表中。哈希表的优点是查找、插入、删除的效率是O(1)。
话不多说,读者可以先试着解答一下,再参考下面的解法。
解答
哈希表
/**
* @author 觅迹
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var intersect = function(nums1, nums2) {
if (nums1.length > nums2.length) {
return intersect(nums2, nums1);
}
const map = {};
const res = [];
for (const num of nums1) { // 记录 nums1 各个数字出现的次数
if (map[num]) {
map[num]++;
} else {
map[num] = 1;
}
}
for (const num of nums2) { // 遍历nums2,取出交集
if (map[num]) {
res.push(num);
map[num]--;
}
}
return res;
};
复杂度分析:
-
时间复杂度:
O(m+n),其中 m 和 n 分别是两个数组的长度。 -
空间复杂度:
O(min(m,n))。
注:我们使用了两次for循环去遍历两个数组,因此,该解法的时间复杂度是O(m+n)。此外,哈希表只需要用到大小为min(m,n)的空间,因此空间复杂度是O(min(m,n))。