【题目】
给定两个数组,编写一个函数来计算它们的交集。
示例 1
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
示例 2
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]
说明
输出结果中每个元素出现的次数,应与元素在两个数组中出现次数的最小值一致。
我们可以不考虑输出结果的顺序。
进阶
如果给定的数组已经排好序呢?你将如何优化你的算法?
如果 nums1 的大小比 nums2 小很多,哪种方法更优?
如果 nums2 的元素存储在磁盘上,内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?
【代码】
【Python】
【方法1】不排序直接处理num1,对其中的字符数量进行统计。
class Solution:
def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
rs=[]
cnt={}
for n in nums1:
if n not in cnt:
cnt[n]=0
cnt[n]+=1
for n in nums2:
if n in cnt and cnt[n]:
cnt[n]-=1
rs.append(n)
return rs
【方法2】Counter
class Solution:
def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
rs=[]
nums1=dict(Counter(nums1))
nums2=dict(Counter(nums2))
print(nums2)
for i in nums2:
if i in nums1:
rs.extend([i]*min(nums1[i],nums2[i]))
return rs
关于进阶部分的三问,面对提出的三种情况给出下面的对策:
【一问】如果给定的数组已经排好序呢?你将如何优化你的算法?
class Solution:
def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
nums1.sort()
nums2.sort()
pos1,pos2=0,0
rs=[]
while pos1<len(nums1) and pos2<len(nums2):
if nums1[pos1]==nums2[pos2]:
rs.append(nums1[pos1])
pos1+=1
pos2+=1
elif nums1[pos1]<nums2[pos2]:
pos1+=1
else:
pos2+=1
return rs
【二问】如果 nums1 的大小比 nums2 小很多,哪种方法更优?
可以使用方法2中的代码,对其简单的改动即可
首先,对nums1,nums2进行处理,对其中的字符进行统计存储在dict中;
然后,选取较小长度的dict作为主元素,遍历这个dict,对于每个key查询,看其是否在dict2中存在,如果存在,则选取二者value的最小值。将该元素加入rs列表中。
【三问】如果 nums2 的元素存储在磁盘上,内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?
- 解决方案:通过归并外排将两个数组排序后再使用排序双指针查找
对应进阶问题三,如果内存十分小,不足以将数组全部载入内存,那么必然也不能使用哈希这类费空间的算法,只能选用空间复杂度最小的算法,即【一问】。
但是【一问】中需要改造,一般说排序算法都是针对于内部排序,一旦涉及到跟磁盘打交道(外部排序),则需要特殊的考虑。归并排序是天然适合外部排序的算法,可以将分割后的子数组写到单个文件中,归并时将小文件合并为更大的文件。当两个数组均排序完成生成两个大文件后,即可使用双指针遍历两个文件,如此可以使空间复杂度最低。
关于外部排序与JOIN,强烈推荐大家看一下 数据库内核杂谈(六):表的 JOIN(连接)这一系列数据库相关的文章
参考:https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/solution/jin-jie-san-wen-by-user5707f/