倒排索引交集问题 | 豆包MarsCode AI刷题

155 阅读3分钟

题目分析

小S需要实现一个搜索引擎的倒排索引功能,其核心是处理两个单词的倒排链,找到包含两个单词的帖子ID交集,并按照从大到小的顺序输出。

倒排索引在信息检索系统中非常重要,其本质是将每个单词与包含该单词的文档ID建立关联,方便快速检索相关内容。本题的关键是高效计算两个有序列表的交集,并满足输出结果按降序排列的要求。


解题思路

由于倒排链是按升序排列的整数列表,我们可以利用其有序性进行优化,避免暴力遍历。

方法选择
  1. 暴力法:直接用嵌套循环,检查每个元素是否在另一个列表中。这种方法的时间复杂度为O(m * n),对于较长的倒排链效率很低。
  2. 双指针法:利用倒排链的有序性,通过双指针从后向前扫描,快速找到交集,时间复杂度为O(m + n),更适合处理大规模数据。

本题采用双指针法,步骤如下:

  1. 初始化两个指针,分别指向两个倒排链的末尾。

  2. 比较当前指针指向的元素:

    • 如果相等,将元素加入结果列表,同时移动两个指针。
    • 如果第一个链的元素较大,移动第一个指针。
    • 如果第二个链的元素较大,移动第二个指针。
  3. 重复上述操作,直到任一指针越界。

  4. 由于是从后往前遍历,交集结果天然按降序排列,不需要额外排序。


代码实现

java
复制代码
import java.util.*;

public class Main {
    public static List<Integer> solution(List<Integer> a, List<Integer> b) {
        int i = a.size() - 1, j = b.size() - 1;
        List<Integer> result = new ArrayList<>();
        
        while (i >= 0 && j >= 0) {
            if (a.get(i).equals(b.get(j))) {
                result.add(a.get(i));
                i--;
                j--;
            } else if (a.get(i) > b.get(j)) {
                i--;
            } else {
                j--;
            }
        }
        
        return result;
    }

    public static void main(String[] args) {
        System.out.println(solution(Arrays.asList(1, 2, 3, 7), Arrays.asList(2, 5, 7)).equals(Arrays.asList(7, 2)));
        System.out.println(solution(Arrays.asList(1, 4, 8, 10), Arrays.asList(2, 4, 8, 10)).equals(Arrays.asList(10, 8, 4)));
        System.out.println(solution(Arrays.asList(3, 5, 9), Arrays.asList(1, 4, 6)).equals(Collections.emptyList()));
        System.out.println(solution(Arrays.asList(1, 2, 3), Arrays.asList(1, 2, 3)).equals(Arrays.asList(3, 2, 1)));
    }
}

关键点解析

  1. 输入有序性: 倒排链输入已经按升序排列,结合双指针法从后向前遍历,避免了排序的开销。
  2. 结果顺序要求: 从后向前遍历使结果天然按降序排列,无需额外的排序步骤。
  3. 时间复杂度: 每次迭代最多移动一个指针,整体复杂度为O(m + n),其中mn是两个倒排链的长度。

测试用例分析

测试用例覆盖了以下情况:

  1. 常见情况:两个倒排链有部分交集。

    • 输入:a = [1, 2, 3, 7], b = [2, 5, 7]
    • 输出:[7, 2]
  2. 无交集:两个倒排链完全不重合。

    • 输入:a = [3, 5, 9], b = [1, 4, 6]
    • 输出:[]
  3. 完全相同:两个倒排链完全一致。

    • 输入:a = [1, 2, 3], b = [1, 2, 3]
    • 输出:[3, 2, 1]
  4. 部分交集且长度不同

    • 输入:a = [1, 4, 8, 10], b = [2, 4, 8, 10]
    • 输出:[10, 8, 4]

这些测试用例验证了代码的正确性和鲁棒性。


优化方向

  1. 输入边界检查: 如果输入列表为空,可直接返回空列表,提升代码健壮性。
  2. 扩展支持多链交集: 当前方案适合两个倒排链交集,若需支持多个链交集,可利用多路归并或逐链交集计算。

总结

本题的核心是利用倒排链的有序性,通过双指针法高效计算交集。该方法简单易实现,时间复杂度和空间复杂度均较优,非常适合在大规模数据处理场景中使用。本题不仅考察了对算法优化的理解,也验证了对问题建模的能力。