问题描述
小S正在帮助她的朋友们建立一个搜索引擎。为了让用户能够更快地找到他们感兴趣的帖子,小S决定使用倒排索引。倒排索引的工作原理是:每个单词都会关联一个帖子ID的列表,这些帖子包含该单词,且ID按从小到大的顺序排列。
例如,单词“夏天”可能出现在帖子1、帖子3和帖子7中,那么这个单词的倒排链就是 [1, 3, 7]。如果用户想同时找到包含“夏天”和“海滩”的帖子,小S需要找出两个倒排链的交集,且将结果按照从大到小的顺序输出。现在,给定两个单词的倒排链数组 a 和 b,请你帮助小S找出同时包含这两个单词的帖子ID,并按从大到小的顺序返回结果。
测试样例
样例1:
输入:
a = [1, 2, 3, 7], b = [2, 5, 7]
输出:[7, 2]
样例2:
输入:
a = [1, 4, 8, 10], b = [2, 4, 8, 10]
输出:[10, 8, 4]
样例3:
输入:
a = [3, 5, 9], b = [1, 4, 6]
输出:[]
样例4:
输入:
a = [1, 2, 3], b = [1, 2, 3]
输出:[3, 2, 1]
问题分析
题目要求我们从两个倒排索引的数组中找出它们的交集,并按从大到小的顺序输出交集的结果。倒排索引数组中已经保证了帖子ID的顺序是从小到大的,因此,我们的目标就是找出两个数组的交集,并且将交集的结果按从大到小排序。
解决方案
-
交集操作:我们需要找出两个列表(
a和b)的交集。可以利用两个指针分别遍历a和b来实现交集的求解。- 由于
a和b都是有序的,我们可以采用类似于归并排序的技巧,使用两个指针i和j,分别指向数组a和b。 - 如果
a[i] == b[j],则这个值是交集的一部分,加入结果并移动两个指针。 - 如果
a[i] < b[j],则移动i,否则移动j。
- 由于
-
排序操作:交集的结果得到后,我们需要将结果按从大到小的顺序输出。
步骤
- 使用双指针方法计算两个数组的交集。
- 将交集数组反转(因为题目要求从大到小的顺序)。
- 输出反转后的交集结果。
代码实现
pythonCopy Code
def intersect_and_reverse(a, b):
# 结果数组
result = []
# 双指针遍历
i, j = 0, 0
while i < len(a) and j < len(b):
if a[i] == b[j]:
result.append(a[i])
i += 1
j += 1
elif a[i] < b[j]:
i += 1
else:
j += 1
# 结果反转,按从大到小顺序输出
result.reverse()
return result
# 测试用例
print(intersect_and_reverse([1, 2, 3, 7], [2, 5, 7])) # 输出:[7, 2]
print(intersect_and_reverse([1, 4, 8, 10], [2, 4, 8, 10])) # 输出:[10, 8, 4]
print(intersect_and_reverse([3, 5, 9], [1, 4, 6])) # 输出:[]
print(intersect_and_reverse([1, 2, 3], [1, 2, 3])) # 输出:[3, 2, 1]
解释
-
双指针方法:
-
我们使用两个指针
i和j,分别指向数组a和数组b的起始位置。 -
每次比较
a[i]和b[j]:- 如果相等,则说明这是两个数组的共同元素,加入结果数组,并同时移动两个指针。
- 如果
a[i] < b[j],说明数组a中的当前元素小于b中的元素,移动指针i。 - 如果
a[i] > b[j],说明数组b中的当前元素小于a中的元素,移动指针j。
-
这个过程一直持续到有一个指针超出数组范围为止。
-
-
反转结果:
- 由于题目要求结果是按从大到小的顺序输出,我们在得到交集之后使用
result.reverse()进行反转。
- 由于题目要求结果是按从大到小的顺序输出,我们在得到交集之后使用
复杂度分析
-
时间复杂度:
- 双指针遍历数组的时间复杂度为 O(min(n,m))O(min(n,m)),其中 nn 和 mm 是数组
a和b的长度。 - 反转操作的时间复杂度为 O(k)O(k),其中 kk 是交集的大小。
- 因此,总的时间复杂度为 O(min(n,m)+k)O(min(n,m)+k),其中 kk 是交集大小。
- 双指针遍历数组的时间复杂度为 O(min(n,m))O(min(n,m)),其中 nn 和 mm 是数组
-
空间复杂度:
- 我们需要一个额外的数组
result来存储交集,空间复杂度为 O(k)O(k),其中 kk 是交集的大小。
- 我们需要一个额外的数组
测试结果
- 测试用例 1: 输入
[1, 2, 3, 7]和[2, 5, 7],交集为[2, 7],反转后输出[7, 2]。 - 测试用例 2: 输入
[1, 4, 8, 10]和[2, 4, 8, 10],交集为[4, 8, 10],反转后输出[10, 8, 4]。 - 测试用例 3: 输入
[3, 5, 9]和[1, 4, 6],没有交集,输出[]。 - 测试用例 4: 输入
[1, 2, 3]和[1, 2, 3],交集为[1, 2, 3],反转后输出[3, 2, 1]。
这样,我们就完成了题目的要求。