哈希表 - 两个数组的交集(集合、数组) - 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;
};
相关推荐
qq. 28040339843 小时前
CSS层叠顺序
前端·css
喝拿铁写前端4 小时前
SmartField AI:让每个字段都找到归属!
前端·算法
猫猫不是喵喵.4 小时前
vue 路由
前端·javascript·vue.js
烛阴4 小时前
JavaScript Import/Export:告别混乱,拥抱模块化!
前端·javascript
bin91535 小时前
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加行拖拽排序功能示例12,TableView16_12 拖拽动画示例
前端·javascript·vue.js·ecmascript·deepseek
GISer_Jing5 小时前
[Html]overflow: auto 失效原因,flex 1却未设置min-height &overflow的几个属性以及应用场景
前端·html
程序员黄同学5 小时前
解释 Webpack 中的模块打包机制,如何配置 Webpack 进行项目构建?
前端·webpack·node.js
拉不动的猪5 小时前
vue自定义“权限控制”指令
前端·javascript·vue.js
再学一点就睡5 小时前
浏览器页面渲染机制深度解析:从构建 DOM 到 transform 高效渲染的底层逻辑
前端·css
拉不动的猪5 小时前
刷刷题48 (setState常规问答)
前端·react.js·面试