问题描述
小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]
解题思路:
问题理解
你需要找出两个有序数组 a 和 b 的交集,并将结果按从大到小的顺序返回。
数据结构选择
由于 a 和 b 是有序数组,我们可以利用双指针法来高效地找到交集。 交集的结果需要按从大到小的顺序排列,因此我们可以使用一个 vector 来存储结果,并在最后反转这个 vector。
算法步骤
初始化双指针:
分别指向数组 a 和 b 的开始位置。
遍历数组:
如果 a[i] 等于 b[j],则将这个值加入结果集,并移动两个指针。
如果 a[i] 小于 b[j],则移动 a 的指针。
如果 a[i] 大于 b[j],则移动 b 的指针。
反转结果集:
由于我们需要从大到小的顺序,最后反转结果集。
最终代码:
import java.util.*;
public class Main {
public static List<Integer> solution(List<Integer> a, List<Integer> b) {
// write code here
int[] arr = new int[50005];//标记数组
int i = 0;
int max = 0;
for(i = 0; i < a.size(); i++){
arr[a.get(i)]++;
max = max > a.get(i) ? max : a.get(i);
}
for(i = 0; i < b.size(); i++){
arr[b.get(i)]++;
max = max > b.get(i) ? max : b.get(i);
}
ArrayList arr1 = new ArrayList<>();
for(i = max; i >= 0;i--)
{
if(arr[i] == 2){
arr1.add(i);
}
}
return arr1;
}
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)));
}
}
个人总结
倒排索引是高效文本检索的基础,能够在大量文档中快速找到包含特定关键词的文档IDs。通过使用 Java 中的集合框架,我们可以很方便地构建这样的数据结构。这个过程不仅提升了查找效率,也为后续的文本分析和信息检索提供了良好的基础。
在实现过程中,我体会到合理的数据结构设计对性能的重要性,以及处理重复数据和查找效率的必要考量。此外,编写清晰的代码和注释也是帮助日后维持和扩展代码的关键。在实际应用中,倒排索引还可以进一步优化,例如实现支持多种查询方式(如短语搜索),或通过合并相邻的文档ID来降低存储占用率。