SWE · Coding

按标签匹配回答者与问题:倒排索引及优先队列

先定义任一标签匹配、全部标签匹配和回答优先级。

题目重点:先定义任一标签匹配、全部标签匹配和回答优先级。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • questions映射questionID→标签集合,person给自己的标签;重复tag去重。
  • 代码支持any交集非空与all人物标签全包含两种合同。优先级字段/更新规则未给,作为设计追问。

解题路线

  1. 建tag→questionIDs倒排。any查询取posting并集,all按最短posting开始交集,空tag在any返回空、all按空集子集定义返回全部。
  2. 倒排省掉与所有问题逐个比较;时间依真正访问posting量,不是无条件O(1)。热门标签仍会产生大量候选。
  3. 若按priority回答,可对候选构建堆;静态批量heapify O(C),取K O(KlogC)。动态priority用版本号惰性删过期项,并明确并发claim避免多人抢答同题。

手动走一遍

问题Q1={python,sql},Q2={python},人={python,sql}:any都匹配,all仅Q1。空标签人按all的数学合同匹配全部,但产品可能要求不匹配,必须显式改规则。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

class Index:
    def __init__(self,questions):
        self.tags={key:set(tags) for key,tags in questions.items()};self.postings={}
        for key,tags in self.tags.items():
            for tag in tags:self.postings.setdefault(tag,set()).add(key)
    def match(self,tags,mode="any"):
        tags=set(tags)
        if mode=="any":
            result=set()
            for tag in tags:result.update(self.postings.get(tag,()))
            return result
        if mode!="all":raise ValueError("mode must be any/all")
        if not tags:return set(self.tags)
        lists=sorted((self.postings.get(tag,set()) for tag in tags),key=len)
        result=set(lists[0])
        for posting in lists[1:]:result.intersection_update(posting)
        return result

复杂度

建索引O(A)空间/时间,A总标签关联。any O(Σposting长度),all实际集合交集成本相关;结果C也有Ω(C)输出。

易错点与追问

容易失分的边界

  • all指问题标签都在人能力里还是人的标签都在问题里,方向不可混淆。
  • 优先级高的问题如果不满足标签不能先弹堆后不计筛选成本。

继续深挖

  • 删除问题和改标签怎样避免索引残留?
  • priority加时间衰减时如何防止队列饥饿?
✓已复制微信号!