题目分析
小S需要实现一个搜索引擎的倒排索引功能,其核心是处理两个单词的倒排链,找到包含两个单词的帖子ID交集,并按照从大到小的顺序输出。
倒排索引在信息检索系统中非常重要,其本质是将每个单词与包含该单词的文档ID建立关联,方便快速检索相关内容。本题的关键是高效计算两个有序列表的交集,并满足输出结果按降序排列的要求。
解题思路
由于倒排链是按升序排列的整数列表,我们可以利用其有序性进行优化,避免暴力遍历。
方法选择
- 暴力法:直接用嵌套循环,检查每个元素是否在另一个列表中。这种方法的时间复杂度为
O(m * n),对于较长的倒排链效率很低。 - 双指针法:利用倒排链的有序性,通过双指针从后向前扫描,快速找到交集,时间复杂度为
O(m + n),更适合处理大规模数据。
本题采用双指针法,步骤如下:
-
初始化两个指针,分别指向两个倒排链的末尾。
-
比较当前指针指向的元素:
- 如果相等,将元素加入结果列表,同时移动两个指针。
- 如果第一个链的元素较大,移动第一个指针。
- 如果第二个链的元素较大,移动第二个指针。
-
重复上述操作,直到任一指针越界。
-
由于是从后往前遍历,交集结果天然按降序排列,不需要额外排序。
代码实现
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)));
}
}
关键点解析
- 输入有序性: 倒排链输入已经按升序排列,结合双指针法从后向前遍历,避免了排序的开销。
- 结果顺序要求: 从后向前遍历使结果天然按降序排列,无需额外的排序步骤。
- 时间复杂度: 每次迭代最多移动一个指针,整体复杂度为
O(m + n),其中m和n是两个倒排链的长度。
测试用例分析
测试用例覆盖了以下情况:
-
常见情况:两个倒排链有部分交集。
- 输入:
a = [1, 2, 3, 7], b = [2, 5, 7] - 输出:
[7, 2]
- 输入:
-
无交集:两个倒排链完全不重合。
- 输入:
a = [3, 5, 9], b = [1, 4, 6] - 输出:
[]
- 输入:
-
完全相同:两个倒排链完全一致。
- 输入:
a = [1, 2, 3], b = [1, 2, 3] - 输出:
[3, 2, 1]
- 输入:
-
部分交集且长度不同:
- 输入:
a = [1, 4, 8, 10], b = [2, 4, 8, 10] - 输出:
[10, 8, 4]
- 输入:
这些测试用例验证了代码的正确性和鲁棒性。
优化方向
- 输入边界检查: 如果输入列表为空,可直接返回空列表,提升代码健壮性。
- 扩展支持多链交集: 当前方案适合两个倒排链交集,若需支持多个链交集,可利用多路归并或逐链交集计算。
总结
本题的核心是利用倒排链的有序性,通过双指针法高效计算交集。该方法简单易实现,时间复杂度和空间复杂度均较优,非常适合在大规模数据处理场景中使用。本题不仅考察了对算法优化的理解,也验证了对问题建模的能力。