anagram中文译为“相同字母异序词”或“易位构词”。它就是将组成一个词或句子的字母(字符)重新排列,形成另一个有意义的词或句子,互为异位词的两个词(句)中每个字母(字符)出现的次数是一致的。
单词级别的异位词
从最常见的简单词汇开始,异位词其实无处不在。
异位词有趣的地方,有一些词汇后者短语在重组后的新词常常与原词的含义有着奇妙的讽刺或幽默关联。
- 宿舍 (dormitory) -> 脏房间 (dirty room):巧妙的吐槽,有画面感了。
- 葬礼 (funeral) -> 真正的乐趣 (real fun):黑色幽默,对生命另一种角度的理解。
- 恋人 (Valentine poem) -> 恋爱的笔友 (pen mate in love):万变不离其宗,还是浪漫主题。
- 签订合同 (signature) -> 真实的证据 (a true sign):用文字游戏诠释了签字的法律效力。
- 餐厅 (restaurant) -> 经营小吃 (runs a treat):生动描绘了餐厅的日常运作。
创意无限:更多精彩的异位词
除了上述关联紧密的例子,异位词世界还有更多奇妙组合。
| |
|---|
| I'm a dot in place (此处一点) |
| |
| |
| |
| Alas! No more Z's (啊!没得睡了) |
名人、文学作品的中异位词
- 《哈利·波特》:大反派 伏地魔 (Voldemort)。他的本名 Tom Marvolo Riddle(汤姆·马沃洛·里德尔) 正是 I am Lord Voldemort (我是伏地魔)的异位词。
- Donald Trump (唐纳德·特朗普) 有变体 Damp old runt (“潮湿的老矮子” or “潮湿的旧布料”)。
- Jennifer Aniston (詹妮弗·安妮斯顿) 可以变成 Fine in torn jeans (“破洞牛仔裤也很美” or “穿牛仔裤很时尚”)。
Python实现是否异位词判断
import re
from collections import Counter
defare_anagrams(s1: str, s2: str, ignore_case: bool = True, ignore_non_alpha: bool = True) -> bool:
"""
判断两个字符串是否互为异位词(Anagram)。
参数:
s1: 第一个字符串(单词或短句)
s2: 第二个字符串
ignore_case: 是否忽略大小写,默认为 True
ignore_non_alpha: 是否忽略非字母字符(如空格、标点、数字),默认为 True
返回:
True 表示互为异位词,False 表示不是
"""
# 1. 统一处理大小写
if ignore_case:
s1 = s1.lower()
s2 = s2.lower()
# 2. 根据需要移除或保留非字母字符
if ignore_non_alpha:
# 只保留 a-z 字母
s1 = re.sub(r'[^a-z]', '', s1)
s2 = re.sub(r'[^a-z]', '', s2)
# 若不忽略非字母字符,则直接使用原字符串(含空格、标点等)
# 3. 比较处理后的字符序列(两种方法任选一种)
# 方法一:排序后比较(简单直观)
# return sorted(s1) == sorted(s2)
# 方法二:使用 Counter 统计字符频率(时间复杂度更优)
return Counter(s1) == Counter(s2)
# ---------- 测试代码 ----------
if __name__ == "__main__":
# 基本单词测试
print(are_anagrams("elvis", "lives"))
# 结果:True
print(are_anagrams("listen", "silent"))
# 结果:True
print(are_anagrams("hello", "world"))
# 结果:False
# 忽略大小写和标点符号的短句测试
print(are_anagrams("Tom Marvolo Riddle", "I am Lord Voldemort"))
# 结果:True
print(are_anagrams("A decimal point", "I'm a dot in place"))
# 结果:True
print(are_anagrams("The Morse code", "Here come dots"))
# 结果:True
# 不忽略非字母字符(严格模式)—— 此时空格和标点必须完全相同
print(are_anagrams("post", "stop", ignore_non_alpha=False))
# 结果:True
print(are_anagrams("post!", "stop", ignore_non_alpha=False))
# 结果:False
分析说明
1. 算法复杂度
- 时间复杂度:O(n + m),其中 n、m 分别为两个字符串处理后的长度。
re.sub 遍历一次,Counter 再遍历一次。 - 空间复杂度:O(k₁ + k₂),k₁、k₂ 为字符串中不同字母的种类数(最多 26 种,忽略大小写)。
2. 适用场景
- 单词级别:最经典的例子(
listen ↔ silent)。 - 短句级别:正常使用应该要启用
ignore_non_alpha=True,因为短句中空格和标点位置常被自由调整(例如 "Tom Marvolo Riddle" 与 "I am Lord Voldemort" 长度和标点符号不同,但字母完全相同)。 - 严格要求:若需要检查包含标点符号的完全一致重排(如
"post!" 与 "stop!"),可设置 ignore_non_alpha=False。
注意事项
- 多字节字符:目前正则只处理
[a-z],对于其他字母(如法语 é、德语 ß)会直接删除。如果需要支持 Unicode 字母,可将正则改为 [^\w] 并配合 re.UNICODE,或使用 str.isalpha() 过滤。 - 数字处理:示例中默认删除数字。若需保留数字(如
"1+2=3" 与 "3+2=1"),可以修改正则 [^a-z0-9] 或增加参数 keep_digits。
扩展
- 对于大规模词汇匹配(如字典中找出所有异位词),可以先将每个单词的标准化形式(排序后字符串或频率元组)作为键,构建哈希表,实现 O(1) 查询。
- 对于中文异位词,需要以字为单位(而不是字母),同样可使用
sorted 或 Counter,但需先进行分词(按字符切分即可)。同时正则表达式也需要调整支持中文。