算法 | 使用 Set 找到两个数组的交集

93 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 21 天,点击查看活动详情

给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

image.png

当看到两个数组的数据的时候,如果不考虑使用暴力解法,不难想到建立新的结构来存储有交集的数据,并且需要进行去重。使用 ES6 中的 Set 结构来进行去重是最简便的方式。

解法一:

  • 两个数组的数据可能是无序的,所以可以先对数据进行排序,再利用双指针分别指向两个数组,依次比较对应的值
  • 比较时,数字小的数组指针进行移动。如果值相同,两个指针同时移动
  • 建立一个空的 Set,每次值相同时,将数据存入进去(.add()方法)
  • 排序使用 sort() 方法:arr.sort((a, b) => a - b)
var intersection = function (nums1, nums2) {
    nums1 = nums1.sort((a, b) => a - b);
    nums2 = nums2.sort((a, b) => a - b);
    let res = new Set();
    let i = 0;
    let j = 0;
    while (i < nums1.length && j < nums2.length) {
        if (nums1[i] < nums2[j]) {
            i++;
        } else if (nums1[i] > nums2[j]) {
            j++;
        } else {
            res.add(nums1[i]);
            i++;
            j++;
        }
    }
    return [...res];
}

解法二:

这一种方法不利用排序,而是找到最长的数组,转换成 Set 结构,利用其 has 函数判断是否包含 短数组的每个元素。

var intersection = function(nums1, nums2) {
    if(nums1.length < nums2.length) {
        const temp = nums1;
        nums1 = nums2;
        nums2 = temp;
    }
    const set1 = new Set(nums1);
    const resSet = new Set();
    for(let i = 0; i <= nums2.length - 1; i++) {
        set1.has(nums2[i]) && resSet.add(nums2[i]);
    }
    return Array.from(resSet);
};

解法三:

function intersection(nums1, nums2) {
    return Array.from(new Set(nums1.filter(i => nums2.includes(i))))
}

这种方式还可以快速求差集和并集:

let difference = new Set([...nums1].filter(x => !nums2.includes(x)));

或者,将两个数组全部转换为 Set 结构之后,使用 nums2.has() 来进行判断。

运行结果

image.png

image.png

去重之后转数组

将 Set 转换为数组结构,有如下的方式:

  1. ES6 的 ... 解构

let arr = [...setArr ];

  1. Array.from(),用来将类数组解析为数组

let arr = Array.from(setArr)