小S的倒排索引题解 | 豆包MarsCode AI 刷题

45 阅读3分钟

问题分析

给定两个倒排索引数组 ab,分别代表单词出现的帖子ID。我们的任务是找出同时包含这两个单词的帖子ID,并按照从大到小的顺序返回结果。

解决思路

  1. 理解倒排链:

    • 数组 a 和 b 分别代表了两个单词的帖子ID列表。每个数组是升序排列的。
    • 我们的目标是找出两个数组的交集,即同时出现在 a 和 b 中的帖子ID。
  2. 交集的寻找:

    • 由于 a 和 b 都是升序排列的,我们可以使用双指针法高效地求解交集。
    • 双指针法:两个指针分别指向 a 和 b 的开头。如果指针指向的元素相同,就将该元素加入结果列表并移动两个指针。如果指向的元素不相同,则移动值较小的那个指针,直到两个指针都走完。
  3. 返回结果:

    • 交集求出来之后,按题目要求需要将结果从大到小排序。可以通过反转结果列表来实现。

算法步骤

  1. 初始化两个指针:分别指向数组 a 和 b 的开始位置。

  2. 双指针遍历

    • 比较指针指向的元素。
    • 如果相等,将该元素加入结果列表,并同时移动两个指针。
    • 如果不相等,移动指向较小值的指针,继续比较。
  3. 反转结果:因为要按从大到小的顺序返回,所以最终将交集结果反转。

  4. 返回结果

代码实现

pythonCopy Code
def find_common_posts(a, b):
    # 双指针初始化
    i, j = 0, 0
    result = []
    
    # 使用双指针法找到交集
    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
    
    # 结果需要从大到小排序
    return result[::-1]

# 输入读取
a = list(map(int, input().split()))
b = list(map(int, input().split()))

# 输出结果
print(find_common_posts(a, b))

解释

  1. 双指针法:我们有两个指针 ij,分别指向数组 ab 的当前元素。每次比较 a[i]b[j]

    • 如果相等,说明这是一个公共帖子ID,加入 result 列表,两个指针都向后移动。
    • 如果 a[i] 小于 b[j],说明 a[i] 没有在 b 中出现,因此只移动 i
    • 如果 a[i] 大于 b[j],说明 b[j] 没有在 a 中出现,因此只移动 j
  2. 反转结果:最终的结果是升序的,而题目要求从大到小,所以使用 result[::-1] 将结果反转。

复杂度分析

  1. 时间复杂度

    • 双指针遍历:由于每次移动一个指针,最多遍历一遍 a 和 b,所以时间复杂度为 O(n + m),其中 n 和 m 分别是数组 a 和 b 的长度。
    • 反转结果:反转一个大小为 min(n, m) 的列表,时间复杂度是 O(min(n, m))
    • 因此,整体时间复杂度是 O(n + m)
  2. 空间复杂度

    • 我们使用了一个额外的列表 result 存储交集,空间复杂度是 O(min(n, m))

示例

输入:

Copy Code
1 2 3 5 6
2 3 4 5 7

输出:

Copy Code
[5, 3, 2]

解释:

  • 数组 a = [1, 2, 3, 5, 6]
  • 数组 b = [2, 3, 4, 5, 7]
  • 交集是 [2, 3, 5]
  • 反转后返回结果 [5, 3, 2]

优化和总结

  • 时间效率:使用双指针法能在线性时间内找到交集,避免了使用暴力方法(例如嵌套循环)的高时间复杂度。
  • 空间效率:通过在原地修改和只使用必要的额外空间,我们保证了空间复杂度较低。