青训营X豆包MarsCode 技术训练营AI刷题-小S的倒排索引| 豆包MarsCode AI 刷题

37 阅读3分钟

解题思路

问题理解

我们需要找出两个有序数组 ab 的交集,并将结果按从大到小的顺序输出。交集的定义是两个数组中都出现的元素。

数据结构选择

由于输入的两个数组是有序的,我们可以利用这一特性来优化查找交集的过程。使用双指针法是一个不错的选择,因为它可以在一次遍历中完成交集的查找,时间复杂度为 O(n + m),其中 n 和 m 分别是两个数组的长度。

算法步骤

  1. 初始化指针:设置两个指针 ij,分别指向数组 ab 的开头。
  2. 遍历数组:使用一个循环,当两个指针都没有超出各自数组的范围时,进行以下操作:
    • 如果 a[i] 等于 b[j],说明找到了一个交集元素,将其加入结果列表,并同时移动两个指针。
    • 如果 a[i] 小于 b[j],说明 a[i] 不可能在 b 中出现,移动 i 指针。
    • 如果 a[i] 大于 b[j],说明 b[j] 不可能在 a 中出现,移动 j 指针。
  3. 反转结果:由于题目要求结果按从大到小的顺序输出,因此在返回结果之前,需要将结果列表反转。

总结

通过双指针法,我们可以高效地找到两个有序数组的交集,并按要求输出结果。这个方法的时间复杂度为 O(n + m),空间复杂度为 O(min(n, m)),其中 n 和 m 分别是两个数组的长度。

代码

def solution(a, b):
    # 初始化两个指针,指向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  # a中的元素小于b中的元素,移动a的指针
        else:
            j += 1  # b中的元素小于a中的元素,移动b的指针
    
    # 将结果反转,按从大到小输出
    return result[::-1]


if __name__ == '__main__':
    print(solution([1, 2, 3, 7], [2, 5, 7]) == [7, 2])
    print(solution([1, 4, 8, 10], [2, 4, 8, 10]) == [10, 8, 4])
    print(solution([3, 5, 9], [1, 4, 6]) == [])
    print(solution([1, 2, 3], [1, 2, 3]) == [3, 2, 1])

优化思路

  1. 减少不必要的反转操作

    • 当前代码在找到交集元素后,先将它们按从小到大的顺序存储在 result 列表中,最后再反转结果。实际上,我们可以直接在找到交集元素时,将其插入到 result 列表的头部,这样就不需要最后再反转结果了。
  2. 减少不必要的比较

    • 在双指针遍历过程中,如果 a[i] 和 b[j] 不相等,我们可以直接跳过一些不必要的比较。例如,如果 a[i] 小于 b[j],我们可以直接将 i 移动到 a 中第一个大于等于 b[j] 的位置。