当前位置: 首页 > news >正文

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

一、Set基础

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


1. Set 的基本特性

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

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 是否包含某个值,返回 booleanmySet.has(2)
clear()清空 SetmySet.clear()
size返回 Set 的元素个数(类似 Array.lengthmySet.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 的区别

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

7. 注意事项

  • NaN 在 Set 中被认为是相同的值:
    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.两个数组的交集

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

示例 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 去重 + 遍历查找

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

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(适用于小规模数据)​

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 但还没复习到,后续会更新。

/**
 * @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;
};

 

相关文章:

  • 华为hcia——Datacom实验指南——配置OSPF路由
  • 【Sa-Token】学习笔记 03 - 认识Sa-Token中常见类
  • Linux线程池实现
  • [吾爱出品] 防窥助手 V1.1
  • GIC硬件
  • C++_STL之list篇
  • 衡石科技HENGSHI SENSE异构数据关联技术深度解析:揭秘5-8倍性能提升背后的“异构过滤“架构
  • 第一讲 感应加热原理与感应熔炼电炉特点
  • Java抽象类:深入理解与应用
  • 前端调试实践与案例场景
  • Redis-08.Redis常用命令-有序集合操作命令
  • Socket函数详解:完整指南
  • 用 Python 实现一个 Benchmark 工具
  • MySQL数据库精研之旅第五期:CRUD的趣味探索(上)
  • Assembly语言的嵌入式调试
  • 实现一个once函数,传入函数参数只执行一次
  • AI推理胜过人脑?思维模型!【33】心流理论思维模型
  • Vue 的 nextTick 是如何实现的?
  • Docker中设置default-ulimits参数解决资源限制问题
  • 尝试想一下,三进制电脑应该怎么玩(一)