给定两个数组 A
和 B
,若数组 A
的某个元素 A[i]
与数组 B
中的某个元素 B[j]
满足 A[i]==B[j]
,则寻找到一个匹配的二元组 (i,j)
,请统计再这两个数组 A
和 B
中,一共存在多少个这样的二元组。
第一行输入数组 A
的长度 M
;
第一行输入数组 B
的长度 N
;
第三行输入数组 A
的值;
第四行输入数组 B
的值。
1 ≤ M, N ≤ 100000
A
,B
数组中数值的取值均小于 100000
输出匹配的二元组个数
5
4
1 2 3 4 5
4 3 2 1
4
若下标从 0
开始,则匹配的二元组分别为 (0,3)
,(1,2)
,(2,1)
,(3,0)
,共计 4
对二元组。
6
3
1 2 4 4 2 1
1 2 3
4
数组 A
和 B
中各个元素的频率我们都需要统计,可以用两个哈希表进行储存,分别记为 cnt_A
和 cnt_B
。接下来我们就来统计能构成的二元组的个数。
接下来我们考虑如何计算二元组的数目。某一个数字 num
在 A
中出现的次数为 cnt_A[num]
,存在两种情况:
B
中没有出现,那么能构成的二元组的个数为 0
B
中出现过,出现次数为 cnt_B[num]
,那么基于简单的乘法原理,能构成的二元组个数为 cnt_A[num] * cnt_B[num]
以示例二为例子:元素 1
在数组 A
中出现了两次,下标分别为 0
和 5
,在数组 B 中出现了一次,下标为 0
,所以对于元素 1
可以构成 2 * 1 = 2
组二元组,分别为 (0, 0)
和 (5, 0)
。元素 2
也可以构成 2
组二元组,分别为 (1, 1)
和 (4, 1)
。所以一共可以构成 2 + 2 = 4
组二元组。
如果我们是使用计数器 Counter()
来储存元素频率,上述两种情况其实可以合并。因为如果 num
不位于 cnt_B
的键中,我们会得到 cnt_B[num] = 0
。因此计算 cnt_A[num]*cnt_B[num] = 0
。
所以我们只需要遍历 cnt_A
中的所有键 num
,计算 cnt_A[num]*cnt_B[num]
的结果并求和即可。
# 题目:2023Q1A-统计匹配的二元组个数
# 分值:200
# 作者:闭着眼睛学数理化
# 算法:哈希表
# 代码看不懂的地方,请直接在群上提问
# 导入collections中的Counter计数器类,使用dict()也可以,但是代码就要多一些判断
from collections import Counter
nA = int(input())
nB = int(input())
cnt_A = Counter(input().split())
cnt_B = Counter(input().split())
# 基于乘法原理,计算能够构成的二元组的个数
print(sum(cnt_A[num] * cnt_B[num] for num in cnt_A))
时间复杂度:O(N+M)
。需要遍历数组构建哈希表。
空间复杂度:O(N+M)
。哈希表所占用空间。
华为OD算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!
课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化
每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!
30+天陪伴式学习,20+直播课时,300+动画图解视频,200+LeetCode经典题,100+华为OD真题,还有简历修改与模拟面试将为你解锁
可查看链接 OD算法冲刺训练课程表 & OD真题汇总(持续更新)
绿色聊天软件戳 sheepvipvip
了解更多
部分哈希表真题可见