039 · Intersection of Two Arrays

algorithm
Published

June 18, 2026

My First Thoughts

这道题要找两个 list 的交集,也就是 nums1nums2 里共同出现过的数字。

第一反应是,这题其实是在考察 intersection 这种操作的底层实现。两个数组放在这里,直接能想到的粗暴解法就是:遍历一个数组,看每个数字在不在另一个数组里。

一开始可能会写成这样:

share = []

for num in nums2:
    if num in nums1:
        share.append(num)

return list(set(share))

这个方向是自然的:如果 num 同时出现在 nums2nums1 里,那它就是交集的一部分。

这里最后用:

list(set(share))

也能处理重复数字。因为 share 里可能会收集到多个相同的数字,先转成 set 可以去重,再转回 list 符合题目要求的返回类型。

但这个写法还有一个更重要的问题:查找成本。这里每次写:

num in nums1

如果 nums1 是 list,Python 可能要从头扫到尾才能确认这个数字在不在里面。数组一长,这个负担就不小。

所以一个很自然的优化是:先把数组变成 set。

nums1_set = set(nums1)
nums2_set = set(nums2)

这样做有两个好处:

  • set 本身会去重,正好符合“答案里每个数字只能出现一次”
  • set 里的查找通常更快,适合反复判断某个数字是否存在

然后再循环一个 set,看它的数字是否也在另一个 set 里。这应该就是正解方向了。

边界上也可以想一下空 list。如果两个都是空,或者一个空一个有,答案肯定是空。循环本身其实能处理这种情况。如果想提前返回,也可以写:

if len(nums1) == 0 or len(nums2) == 0:
    return []

注意 Python 里不是 nums1.length,而是 len(nums1)。不过这道题原始约束里两个数组长度都至少是 1,所以这个判断不是必须的。


Why That Is Not Enough

这道题主要考察:list 和 set 在查找效率上的差别

如果用最开始的 list 写法:

share = []

for num in nums2:
    if num in nums1:
        share.append(num)

return list(set(share))

最后的 set(share) 已经能完成去重。真正值得关注的是这一句:

num in nums1

nums1 是 list 时,in 通常要从左到右找。最坏情况下,要把整个 nums1 扫一遍才能知道当前数字在不在里面。

而这个查找发生在循环里面:

for num in nums2:
    if num in nums1:
        ...

也就是说,nums2 里的每个数字,都可能触发一次对 nums1 的线性查找。这就是 list 写法的主要成本。

这题想考察的转折点就是:如果后面会反复问“某个数字是否存在”,可以先把被查询的一边变成 set。

set 更适合做 membership check:

  • num in nums1:在 list 里查找,可能要逐个比较
  • num in nums1_set:在 set 里查找,平均更快

结果也可以继续用 set 保存,这样去重不必等到最后统一处理,而是在加入答案时自然完成。


Final Idea

从原来的想法出发:

for num in nums2:
    if num in nums1:
        share.append(num)

核心逻辑不用变,还是“遍历一个数组,检查数字是否出现在另一个数组里”。

要改的是两个容器:

  1. nums1 先转成 nums1_set,让 num in nums1_set 查得更快
  2. share 改成 set,这样同一个数字加多次也只会保留一份

也就是:

nums1_set = set(nums1)
share = set()

然后遍历 nums2

for num in nums2:
    if num in nums1_set:
        share.add(num)

最后题目要求返回数组,所以把 set 转回 list:

return list(share)

结果顺序不重要,所以 set 转成 list 后顺序不固定也没关系。


Why It Works

nums1_set 保存了 nums1 中出现过的所有不同数字。

遍历 nums2 时,对于每个 num

  • 如果 num in nums1_set,说明它既出现在 nums2,也出现在 nums1,所以它属于交集
  • 如果不在,说明它不是两个数组共同拥有的数字,跳过

结果用 share 这个 set 来保存。set 的特点是同一个值只能出现一次,所以即使 nums2 里有多个相同的数字,最后答案里也只会保留一份。

因此这个过程既找到了两个数组共有的数字,也满足了题目“每个数字只能出现一次”的要求。


Code

def intersection(nums1, nums2):
    nums1_set = set(nums1)
    share = set()

    for num in nums2:
        if num in nums1_set:
            share.add(num)

    return list(share)

如果想写得更短,Python 也可以直接使用 set 的交集操作:

def intersection(nums1, nums2):
    return list(set(nums1) & set(nums2))

第一种写法更适合练习这道题的核心过程:先把 list 变成 set,再用 membership check 判断是否共同出现。


Complexity

Time \(O(n + m)\) - nnums1 的长度,mnums2 的长度;先遍历 nums1 建 set,再遍历 nums2 查找
Space \(O(n + k)\) - nums1_set 最多保存 nums1 中的不同数字,share 保存交集中的不同数字

Takeaway

当题目反复问“这个元素在不在另一个集合里”时,要警觉 list 查找可能会反复扫描。把 list 转成 set,通常能把“查找是否存在”这件事表达得更直接,也更高效;如果答案还要求去重,set 也正好能顺手解决重复问题。


Quiz