LeetCode探索(六):350_两个数组的交集 II

528 阅读2分钟

这是我参与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))。