前端刷题路-Day97:两个数组的交集(题号349)

838 阅读3分钟

这是我参与8月更文挑战的第31天,活动详情查看:8月更文挑战

两个数组的交集(题号349)

题目

给定两个数组,编写一个函数来计算它们的交集。

示例 1:

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

示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]

说明:

  • 输出结果中的每个元素一定是唯一的。
  • 我们可以不考虑输出结果的顺序。

链接

leetcode-cn.com/problems/in…

解释

这题啊,这题是经典简我击。

解法确实不是很难,但要完美的做出来还是要费一番功夫的。

题目的意思很好理解,就取交集呗,这没啥,需要注意的是说明中的一句话:

  • 输出结果中的每个元素一定是唯一的。

这个唯一怎么说?其实有两种解决办法:

  1. 把两个原数组去重,这样就不会有重复数字出现的情况了
  2. 在结果中去重,每次插入新元素时都判断答案中是否出现这一数字,如果出现就不做处理,没有就推进去

其实笔者感觉方案一会好些,因为两个原始数组去重后,循环的次数也会相应的减少,需要做的处理也会少一些,而且可以利用Set来去重,一步到位

那还有一个问题需要处理——怎样最方便的解决两个数组的大小问题?

因为求交集,肯定要先循环短的数组,拿到每个元素后在长的数组中进行查找,如果有就推入结果中,如果没有就GG

如果先循环长数组,必然会浪费一些循环次数,所以先循环短数组是必须的

先找出短数组其实有一种方法十分简单,在函数的一开始就判断参数一的长度是否长与参数二,如果更长,那就进行递归调用,替换两个参数的位置,一步到位

这样该函数的第一个参数永远是长度较短的那一个,后续直接进行比较即可

这种方法大家应该都能想的出来,那有没有更好一点的方案呢?

显然是有的

双指针就是一个不错的选择,首先,对原生的两个数组进行排序,再给这两个数组一人一个指针,都从0开始,然后一点点递增,如果两个指针指向的元素一样,就推入到结果中去,对结果进行判断

这里就要用到第二种保持唯一性的方法了,每次推入前先检查结果中是否存在,如果存在就啥也不干,不存在就推入进去,同样也可以使用Set,更加方便一些。

如果俩指针指向的元素不一样,那就让值更小的指针往前挪一点,因为数组是排过序的,所以会逐渐增大,这样下去一直到走完一个数组就好

这样当一个指针走到尽头就可以拿到最后的答案, 非常好理解的一个双指针。

自己的答案(暴力)

其实也不能说是暴力吧,就正常答案。

var intersection = function(nums1, nums2) {
  if (nums1.length > nums2.length) {
    return intersection(nums2, nums1)
  }
  nums1 = new Set(nums1)
  nums2 = new Set(nums2)
  const res = []
  for (const num of nums1) {
    if (nums2.has(num)) {
      res.push(num)
    }
  }
  return res
};

利用Set对数组进行去重,之后从短的数组开始循环,非常顺利的就可以拿到答案

更好的方法(双指针)

var intersection = function(nums1, nums2) {
  nums1.sort((a, b) => a - b)
  nums2.sort((a, b) => a - b)
  const len1 = nums1.length
  const len2 = nums2.length
  let index1 = 0
  let index2 = 0
  const res = new Set()
  while (index1 < len1 && index2 < len2) {
    const num1 = nums1[index1]
    const num2 = nums2[index2]
    if (num1 === num2) {
      if (!res.has(num1)) res.add(num1)
      index1++
      index2++
    } else if (num1 < num2) {
      index1++
    } else {
      index2++
    }
  }
  return Array.from(res)
};

前期准备比较多,首先对数组进行排序,sort一下就好

之后拿到两个数组的长度,因为后面while会多次读取,所以取出来会好些

再搞两个指针,一开始都是0,也就是数组的第一个元素

准备工作做完之后就开始移动指针了,搞到两个指针指向的元素,先判断是否相等,如果相等判断要不要推入结果中,如果不相等移动较小的那个指针,干就完事了

最后将Set转化成数组返回即可,So easy!



PS:想查看往期文章和题目可以点击下面的链接:

这里是按照日期分类的👇

前端刷题路-目录(日期分类)

经过有些朋友的提醒,感觉也应该按照题型分类
这里是按照题型分类的👇

前端刷题路-目录(题型分类)