给定两个数组,编写一个函数来计算它们的交集。
示例 1:输入:nums1 = [1,2,2,1], nums2 = [2,2] 输出:[2,2]
示例 2: 输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4] 输出:[4,9]
说明:输出结果中每个元素出现的次数,应与元素在两个数组中出现次数的最小值一致。我们可以不考虑输出结果的顺序。
解题思路:
有两种方法:哈希表、排序+双指针,但是如果nums2的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中。那么就无法高效地对nums2 进行排序,因此推荐使用哈希表而不是排序+双指针。在哈希表中,nums2 只关系到查询操作,因此每次读取 nums2 中的一部分数据,并进行处理即可。因此本文将采用哈希表方法进行解答。
算法流程:
由于同一个数字在两个数组中都可能出现多次,因此需要用哈希表存储每个数字出现的次数。对于一个数字,其在交集中出现的次数等于该数字在两个数组中出现次数的最小值。
- 首先,遍历第一个数组,并在哈希表中记录第一个数组中的每个数字以及对应出现的次数;
- 然后,遍历第二个数组,对于第二个数组中的每个数字,如果在哈希表中存在这个数字,则将该数字添加到答案,并减少哈希表中该数字出现的次数;
- 为降低空间复杂度,首先遍历较短的数组并在哈希表中记录每个数字以及对应出现的次数,然后遍历较长的数组得到交集。
代码:
class Solution:
def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
if len(nums1) > len(nums2):
return self.intersect(nums2, nums1)
m = collections.Counter()
for num in nums1:
m[num] += 1
intersection = list()
for num in nums2:
if (count := m.get(num, 0)) > 0:
intersection.append(num)
m[num] -= 1
if m[num] == 0:
m.pop(num)
return intersection
其中,m = collections.Counter()中Counter是dict子类,用于计数可哈希的对象。它是无序的,元素被作为字典的key存储,其计数作为字典的value存储。例如:
from collections import Counter
list_01 = [1,9,9,5,8,8,9]
print(Counter(list_01)) #counter({9:3,8:2,1:1})
另外,if (count := m.get(num, 0)) > 0,:= 赋值表达式运算符(也称为海象运算符)发布于 Python 3.8. 运算符使值的赋值可以传递到表达式中。 这通常会使语句数减少一个。
n=0
while n<6:
print(n)
n+=1
~~~~~~~~~~海象运算符
n=0
while (n:= n+1)<6:
print(n)
.get(num,default) 函数返回指定键的值。dict.get(key, default=None) 如果键不在字典中返回默认值 None 或者设置的默认值。
复杂度:
- 时间复杂度:O(m+n),其中m和n分别是两个数组的长度。需要遍历两个数组并对哈希表进行操作,哈希表操作的时间复杂度为O(1),因此总时间复杂度与两个数组的长度和呈线性关系;
- 空间复杂度:O(min(m,n)),其中m和n分别是两个数组的长度。对较短的数组进行哈希表操作,哈希表的大小不会超过较短的数组的长度。
参考链接:
https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/solution/liang-ge-shu-zu-de-jiao-ji-ii-by-leetcode-solution/