LeetCode热题(JS版) - 350. 两个数组的交集 II

117 阅读2分钟

题目

给定两个数组,编写一个函数来计算它们的交集。

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]
 

说明:

输出结果中每个元素出现的次数,应与元素在两个数组中出现次数的最小值一致。
我们可以不考虑输出结果的顺序。
进阶:

如果给定的数组已经排好序呢?你将如何优化你的算法?
如果 nums1 的大小比 nums2 小很多,哪种方法更优?
如果 nums2 的元素存储在磁盘上,内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?

解题思路

本题可以使用哈希表来解决。首先遍历第一个数组,并将每个元素及其出现的次数存储在哈希表中。然后遍历第二个数组,在哈希表中查找相同的元素,如果存在且出现次数大于 0,则将该元素添加到结果数组中,并将其出现次数减一。

具体实现方式为:

  • 创建一个哈希表 map
  • 遍历第一个数组 nums1,并将每个元素及其出现次数存储在 map 中。
  • 创建一个空数组 result
  • 遍历第二个数组 nums2,并在 map 中查找对应元素,如果存在且出现次数大于 0,则将该元素添加到 result 中,并将其出现次数减一。
  • 返回 result 数组作为最终的交集结果。

代码实现

function intersect(nums1: number[], nums2: number[]): number[] {
    const map = new Map();
    for (const num of nums1) {
        if (!map.has(num)) {
            map.set(num, 0);
        }
        map.set(num, map.get(num) + 1);
    }

    const result: number[] = [];
    for (const num of nums2) {
        if (map.has(num) && map.get(num) > 0) {
            result.push(num);
            map.set(num, map.get(num) - 1);
        }
    }

    return result;
}

也可以双指针法

function intersect(nums1: number[], nums2: number[]): number[] {
    nums1.sort((a, b) => a - b);
    nums2.sort((a, b) => a - b);

    const result: number[] = [];
    let p1 = 0;
    let p2 = 0;

    while (p1 < nums1.length && p2 < nums2.length) {
        if (nums1[p1] === nums2[p2]) {
            result.push(nums1[p1]);
            p1++;
            p2++;
        } else if (nums1[p1] < nums2[p2]) {
            p1++;
        } else {
            p2++;
        }
    }

    return result;
}

复杂度分析

  • 时间复杂度:O(n + m),其中 n 和 m 分别是两个输入数组的长度。遍历第一个数组需要 O(n) 的时间,构建哈希表的过程中需要 O(n) 的时间;遍历第二个数组需要 O(m) 的时间,在哈希表中查找元素的过程中需要 O(1) 的时间。
  • 空间复杂度:O(min(n, m)),其中 n 和 m 分别是两个输入数组的长度。哈希表中存储了较短数组的元素及其出现次数。最坏情况下,当两个数组没有交集时,哈希表中存储的元素为较短数组的所有元素。