哈希表 · 3/5

两个数组的交集

实现求两个数组交集的多种方法

问题

给定两个数组 nums1nums2,返回它们的交集。输出结果中的每个元素必须是唯一的,顺序不限。

示例:

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

解答

方法一:使用 Set

function intersection(nums1, nums2) {
  // 将第一个数组转为 Set,去重并提供 O(1) 查找
  const set1 = new Set(nums1);
  // 用于存储交集结果
  const result = new Set();
  
  // 遍历第二个数组,检查元素是否在 set1 中
  for (const num of nums2) {
    if (set1.has(num)) {
      result.add(num);
    }
  }
  
  return [...result];
}

// 测试
console.log(intersection([1, 2, 2, 1], [2, 2])); // [2]
console.log(intersection([4, 9, 5], [9, 4, 9, 8, 4])); // [4, 9]

方法二:使用 filter + Set(简洁写法)

function intersection(nums1, nums2) {
  const set2 = new Set(nums2);
  // 过滤出在 set2 中存在的元素,再去重
  return [...new Set(nums1.filter(num => set2.has(num)))];
}

// 测试
console.log(intersection([1, 2, 2, 1], [2, 2])); // [2]

方法三:排序 + 双指针

function intersection(nums1, nums2) {
  // 先排序
  nums1.sort((a, b) => a - b);
  nums2.sort((a, b) => a - b);
  
  const result = [];
  let i = 0, j = 0;
  
  while (i < nums1.length && j < nums2.length) {
    if (nums1[i] === nums2[j]) {
      // 避免重复添加
      if (result.length === 0 || result[result.length - 1] !== nums1[i]) {
        result.push(nums1[i]);
      }
      i++;
      j++;
    } else if (nums1[i] < nums2[j]) {
      i++;
    } else {
      j++;
    }
  }
  
  return result;
}

// 测试
console.log(intersection([1, 2, 2, 1], [2, 2])); // [2]

扩展:保留重复元素的交集

如果要求交集中保留重复元素(出现次数取较小值):

function intersect(nums1, nums2) {
  // 用 Map 统计 nums1 中每个元素的出现次数
  const map = new Map();
  for (const num of nums1) {
    map.set(num, (map.get(num) || 0) + 1);
  }
  
  const result = [];
  for (const num of nums2) {
    if (map.get(num) > 0) {
      result.push(num);
      map.set(num, map.get(num) - 1);
    }
  }
  
  return result;
}

// 测试
console.log(intersect([1, 2, 2, 1], [2, 2])); // [2, 2]
console.log(intersect([4, 9, 5], [9, 4, 9, 8, 4])); // [4, 9]

关键点

  • Set 提供 O(1) 的查找效率,是处理去重和交集的首选
  • 双指针法需要先排序,适合数组已排序或空间受限的场景
  • 时间复杂度:Set 方法 O(m+n),双指针 O(mlogm + nlogn)
  • 注意区分”去重交集”和”保留重复的交集”两种变体
  • Map 用于统计频次,处理需要保留重复元素的情况