哈希表 - 两个数组的交集(集合、数组) - JS

一、Set基础

在 JavaScript 中,Set 是一种集合(Collection)​ 数据结构,用于存储唯一值 ​(不允许重复),并且可以高效地进行添加、删除、查询 等操作。它类似于数组(Array),但成员的值都是唯一的,没有重复项。


1. Set 的基本特性

  • 存储唯一值Set 不会存储重复的值,如果尝试添加重复值,会被自动忽略。
  • 无序存储Set 中的元素没有索引,遍历顺序与插入顺序一致,但不支持索引访问(如 set[0])。
  • 可迭代 :可以使用 for...offorEach 遍历 Set 中的元素。
  • 支持任意数据类型 :可以存储 numberstringobjectfunction 等,但 NaNundefined 也可以被存储。

2. 创建 Set

复制代码
const mySet = new Set(); // 空 Set
const mySet2 = new Set([1, 2, 3, 4, 4, 5]); // 自动去重,最终存储 [1, 2, 3, 4, 5]

3. Set 的常用方法

方法 描述 示例
add(value) 添加一个值,返回 Set 本身(可链式调用) mySet.add(10).add(20)
delete(value) 删除某个值,返回 boolean(是否删除成功) mySet.delete(1)
has(value) 检查 Set 是否包含某个值,返回 boolean mySet.has(2)
clear() 清空 Set mySet.clear()
size 返回 Set 的元素个数(类似 Array.length mySet.size

示例:​

复制代码
const set = new Set();

set.add(1); // Set { 1 }
set.add(2); // Set { 1, 2 }
set.add(2); // 重复值,被忽略
set.add("hello"); // Set { 1, 2, "hello" }

console.log(set.size); // 3
console.log(set.has(1)); // true
set.delete(1); // true
console.log(set.has(1)); // false

4. Set 的遍历方法

Set 是可迭代的,可以使用以下方式遍历:

​**(1) for...of 循环**

复制代码
const set = new Set([1, 2, 3]);

for (const item of set) {
  console.log(item); // 1, 2, 3
}

​**(2) forEach 方法**

复制代码
set.forEach((value) => {
  console.log(value); // 1, 2, 3
});

​**(3) 转换成数组(Array.from[...set])​**

复制代码
const arr = Array.from(set); // [1, 2, 3]
const arr2 = [...set]; // [1, 2, 3]

5. Set 的应用场景

​**(1) 数组去重**

复制代码
const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueArr = [...new Set(arr)]; // [1, 2, 3, 4, 5]

​**(2) 判断元素是否存在(比 Array.includes 更快)​**

复制代码
const set = new Set([1, 2, 3]);
console.log(set.has(2)); // true

​**(3) 存储非重复对象(需注意引用类型)​**

复制代码
const obj1 = { name: "Alice" };
const obj2 = { name: "Bob" };
const set = new Set([obj1, obj2, obj1]); // 存储 obj1 和 obj2(obj1 只存一次)

​**(4) 数学集合运算(并集、交集、差集)​**

复制代码
const setA = new Set([1, 2, 3]);
const setB = new Set([2, 3, 4]);

// 并集
const union = new Set([...setA, ...setB]); // Set {1, 2, 3, 4}

// 交集
const intersection = new Set([...setA].filter(x => setB.has(x))); // Set {2, 3}

// 差集(A - B)
const difference = new Set([...setA].filter(x => !setB.has(x))); // Set {1}

6. Set 与 Array 的区别

特性 Set Array
唯一性 不允许重复值 允许重复值
索引访问 不支持 set[0] 支持 arr[0]
查找效率 has() 是 O(1) includes() 是 O(n)
顺序 插入顺序 索引顺序
方法 add() / delete() push() / pop()

7. 注意事项

  • NaNSet 中被认为是相同的值:

    复制代码
    const set = new Set();
    set.add(NaN);
    set.add(NaN); // 只会存一个 NaN
  • Set 存储对象时,比较的是引用 而非值:

    复制代码
    const obj1 = { a: 1 };
    const obj2 = { a: 1 };
    set.add(obj1);
    set.add(obj2); // 会存储两个对象,因为引用不同

总结

  • Set 是一种存储唯一值 的集合,适用于去重、快速查找、集合运算等场景。
  • 主要方法:add()delete()has()clear()size
  • 遍历方式:for...offorEach[...set]
  • 相比数组,Set去重和查找方面更高效,但不支持索引访问。

如果你需要存储不重复的值,并且希望高效地判断某个值是否存在,Set 是一个很好的选择!

二、349.两个数组的交集

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

示例 1:

复制代码
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

示例 2:

复制代码
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

方法 1:使用 Set 去重 + 遍历查找

javascript 复制代码
function intersection(nums1, nums2) {
    const set1 = new Set(nums1);
    const set2 = new Set(nums2);
    const result = [];

    for (const num of set1) {
        if (set2.has(num)) {
            result.push(num);
        }
    }

    return result;
}

方法 2:使用 Set + Array.filter

javascript 复制代码
function intersection(nums1, nums2) {
    const set1 = new Set(nums1);
    const set2 = new Set(nums2);
    return [...set1].filter(num => set2.has(num));
}

方法 3:仅使用 Set + Array.includes(适用于小规模数据)​

javascript 复制代码
function intersection(nums1, nums2) {
    const uniqueNums1 = [...new Set(nums1)];
    return uniqueNums1.filter(num => nums2.includes(num));
}

总结

  • 使用 Set 去重 是解决此类问题的关键。
  • 遍历查找交集 时,Set.has()Array.includes() 更高效(O(1) vs O(n))。
  • 返回结果顺序不重要,因此直接返回过滤后的数组即可。

350. 两个数组的交集 II

给你两个整数数组 nums1nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。

示例 1:

复制代码
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]

示例 2:

复制代码
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]

提示:

  • 1 <= nums1.length, nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 1000

需要统计次数,就需要用上数组了。也可以用map 但还没复习到,后续会更新。

javascript 复制代码
/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersect = function(nums1, nums2) {
    let hashs = new Array(1001).fill(0);
    let result=[];
    for(let i=0;i<nums1.length;i++){
        hashs[nums1[i]]++;
    }
    for(let i=0;i<nums2.length;i++){
        if(hashs[nums2[i]]>0) {
         result.push(nums2[i]);
         hashs[nums2[i]]--;  
        }
    }
    return result;
};
相关推荐
lyc2333333 分钟前
鸿蒙IME Kit高级开发:共享沙箱与跨进程数据传输🚀
前端
lyc2333333 分钟前
鸿蒙UTD详解:标准化数据类型的跨端协作密钥🔑
前端
Hilaku4 分钟前
用好了 defineProps 才叫会用 Vue3,90% 的写法都错了
前端·javascript·vue.js
古夕4 分钟前
前端模块化与Webpack打包原理详解
前端·webpack
lyc2333334 分钟前
鸿蒙自定义编辑框:与输入法交互的3个核心步骤📝
前端
英宋6 分钟前
ckeditor5的研究 (2):对 CKEditor5 进行设计,并封装成一个可用的 vue 组件
前端·javascript
古夕6 分钟前
搞定滚动穿透
前端·javascript
英宋7 分钟前
ckeditor5的研究 (3):初步使用 CKEditor5 的 事件系统 和 API
前端·javascript
lyc23333311 分钟前
鸿蒙多子类型输入法:3步实现输入模式自由切换🔤
前端
Danta11 分钟前
从 0 开始学习 Three.js(2)😁
前端·javascript·three.js