题目重点:目标词和每个候选比较字符多重集,保留列表原有顺序和重复元素;多次查询可预建签名索引。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练版 anagram 是字符频次完全相同,可重新排列;大小写敏感,不做 Unicode 规范化。
- 保留输入列表顺序和重复词项,返回所有匹配字符串;空目标只匹配空字符串。
- 一次查询对每个候选计数字符;大量目标查询时按排序字符或频次 tuple 预建 signature→词列表索引。
解题路线
- 先比较候选长度,长度不同不可能是同字符多重集。
- 对目标构建 Counter,对每个等长候选计数并比较;Counter 保留重复字符数量,不会把 'aab' 与 'abb' 错判相同。
- 若字符集固定且较小,可用定长频次数组作为键;若字符集未知,用 Counter 或排序后的字符 tuple,注意规范化政策必须全程一致。
- 结果按遍历顺序 append,自然保留输入中的重复项;签名索引适合多次查询,但更新列表时需保持顺序元数据。
手动走一遍
words=['eat','tea','tan','ate','eat'],target='tae' 返回 ['eat','tea','ate','eat'];第二个 'eat' 是不同输入位置,训练版保留。target='aab' 不匹配 'abb',虽然两者字符种类相同。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
"""Preserve input order while returning words anagrammatic to the target."""
from collections import Counter
def find_anagrams(words: list[str], target: str) -> list[str]:
expected = Counter(target)
return [word for word in words if len(word) == len(target) and Counter(word) == expected]
复杂度
M 个候选、总字符数 C、目标长 T:计数比较预期 O(C+T) 时间、临时空间 O(目标与单候选不同字符数);多查询预索引需 O(C) 建索引与存词引用,查询还需输出匹配项。
易错点与追问
容易失分的边界
- 用字符集合而不是频次,重复字符数量丢失。
- 对列表去重,意外删掉多个输入位置的相同词。
- 没有声明大小写/Unicode 规范化,却声称所有语言正确。
- 每次多查询都重新扫描大列表而没有考虑索引。
继续深挖
- 支持忽略大小写和重音时如何统一规范化?
- 百万候选词多次查询怎样设计签名索引?
- 若返回下标而不是词,重复元素如何处理?
