51mee - AI智能招聘平台Logo
模拟面试题目大全招聘中心会员专区

设计一个用户搜索功能(如Office搜索文档),需要支持模糊查询、关键词排序(相关性、时间、热度),请说明搜索算法(如倒排索引)、数据结构(Trie树、哈希表)及实现优化。

微软Product Manager Intern难度:困难

答案

1) 【一句话结论】采用倒排索引为核心索引结构,结合Trie树加速前缀匹配,通过哈希表存储文档元数据,并利用多维度排序算法(如TF-IDF+时间+热度),同时设计分布式分片和缓存优化,支持模糊查询及大规模数据场景。

2) 【原理/概念讲解】倒排索引是搜索引擎核心,将每个关键词映射到包含该关键词的文档ID列表,类似图书馆“书名-书架位置”索引,支持多关键词查询(如“搜索文档”同时匹配“搜索”和“文档”)。Trie树(前缀树)用于前缀匹配,节点代表字符,路径为前缀,叶子节点标记文档,如手机输入法输入“offic”时快速定位“office.doc”“official.pdf”。哈希表用于文档元数据(ID、时间、热度),通过哈希函数实现O(1)时间复杂度查找,如手机通讯录查联系人。排序算法中,TF-IDF计算关键词相关性(高频低频词权重),时间排序(新文档优先,如最近24小时内的文档权重更高),热度排序(热门文档,如被分享或下载次数多的文档优先)。

3) 【对比与适用场景】

数据结构/算法定义特性使用场景注意点
倒排索引关键词→文档ID列表的映射支持多关键词查询,查询时合并文档集主流搜索引擎核心(如搜索“搜索文档”)需维护更新,存储开销大(每个关键词对应文档列表)
Trie树前缀树结构,节点代表字符支持前缀匹配,快速查找模糊查询(前缀)、自动补全(如输入“offic”时推荐文档)空间开销大(节点数量随前缀数量增长),适合前缀场景
哈希表基于哈希函数的键值对存储O(1)查找、插入、删除文档元数据(ID、时间、热度)快速查询哈希冲突需处理(如链地址法、开放地址法)

4) 【示例】
伪代码展示索引构建和查询处理(以用户输入“offic*”为例):

  • 索引构建:
    inverted_index = {}  # 字典:关键词→文档ID列表
    trie = Trie()        # 前缀树
    hash_map = {}        # 文档ID→元数据(时间、热度)
    
    for doc_id, content, metadata in documents:
        for word in content.split():
            inverted_index.setdefault(word, []).append(doc_id)
        for word in content.split():
            trie.insert(word)
        hash_map[doc_id] = {
            "time": metadata["time"],
            "popularity": metadata["popularity"]
        }
    
    # 查询处理(模糊查询“offic*”)
    query = "offic*"
    if "*" in query:
        prefix, suffix = query.split("*")
        prefix_docs = trie.search_prefix(prefix)  # 前缀匹配(如“offic”)
        suffix_docs = inverted_index.get(suffix, [])  # 后缀匹配(如“*”)
        result = set(prefix_docs) | set(suffix_docs)  # 去重合并
    else:
        result = set(inverted_index.get(query, []))  # 精确匹配
    
    # 排序(多维度)
    sorted_result = sort_by(
        result,
        hash_map,
        relevance_func=lambda docs: tfidf(docs),  # 相关性
        time_func=lambda docs: -min(docs, key=lambda d: hash_map[d]["time"]),  # 时间(新优先)
        popularity_func=lambda docs: max(docs, key=lambda d: hash_map[d]["popularity"])  # 热度(热门优先)
    )
    

5) 【面试口播版答案】
面试官您好,针对Office搜索文档的需求,我的设计核心是构建一个高效的多维度搜索系统。首先,采用倒排索引作为核心索引结构,它通过将每个关键词映射到包含该关键词的文档列表,支持多关键词查询(如“搜索文档”同时匹配“搜索”和“文档”),这是搜索引擎的基础。然后,结合Trie树加速前缀匹配(如用户输入“offic”时,快速找到所有以“offic”开头的文档,比如“office.doc”“official.pdf”),提升模糊查询的响应速度。同时,用哈希表存储文档元数据(如创建时间、热度),实现O(1)时间复杂度的元数据查询。对于排序,通过TF-IDF计算关键词相关性(高频低频词权重),结合文档时间(新文档优先,比如最近24小时内的文档权重更高)和热度(热门文档,如被分享或下载次数多的文档优先)进行多维度排序。在优化方面,对热门查询结果(如“report”)进行缓存(如Redis LRU缓存,淘汰最少使用的缓存项),对搜索结果进行内存分页(比如每页10条结果,避免内存溢出),并采用分布式分片(如将倒排索引按文档ID范围分片,部署在多个节点上,利用Elasticsearch的分布式查询),确保大规模数据下的性能。这样既能满足模糊查询(如“search*”)、多排序需求,又能保证系统性能。

6) 【追问清单】

  • 问题1:如何处理实时更新的文档(如新上传的文档立即出现在搜索结果中)?
    回答要点:通过增量索引更新倒排索引,结合消息队列(如Kafka)实时推送新文档到索引,确保搜索结果实时性。
  • 问题2:大规模数据下,倒排索引的存储和查询性能如何优化?
    回答要点:采用分片(Sharding)将倒排索引分片存储,利用分布式索引(如Elasticsearch)分片查询,结合缓存(如Redis)缓存热门查询结果,减少磁盘I/O。
  • 问题3:模糊查询(如“search*”)的算法复杂度如何?如何优化?
    回答要点:将模糊查询拆分为前缀匹配(Trie树,O(L)时间,L为前缀长度)和后缀匹配(倒排索引,O(K)时间,K为后缀长度),通过并集操作合并结果,减少重复计算,复杂度为O(L + K),比全文本扫描高效。
  • 问题4:排序权重(如相关性、时间、热度的权重分配)如何确定?
    回答要点:通过A/B测试和用户反馈调整权重,比如用户更关注相关性,则相关性权重设为0.6,时间权重0.2,热度权重0.2;新文档用户更关注时效性,时间权重提升至0.4。
  • 问题5:搜索结果去重(如多个文档包含相同关键词)如何处理?
    回答要点:在倒排索引查询后,通过文档ID去重(set集合),确保每个文档只出现一次,避免重复结果。

7) 【常见坑/雷区】

  • 忽略模糊查询的算法(如仅支持精确匹配),导致“search*”无法正确处理,比如“search*”应匹配前缀“search”和后缀“*”的文档,需合并结果并去重。
  • 排序权重设计不合理(如未考虑用户需求),导致排序结果不符合预期,比如用户期望新文档优先,但权重分配错误。
  • 未考虑分页性能,大规模搜索时内存占用过高,导致响应延迟或系统崩溃。
  • 倒排索引更新机制设计不当,导致新文档无法及时出现在搜索结果中,比如增量更新延迟。
  • 数据结构选择错误(如用数组而非哈希表存储文档元数据),导致查询效率低下,比如查找元数据需要O(n)时间。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1