LeetCode 205简单哈希表
同构字符串 图解题解
这道题到底在问什么
给定两个字符串 s 和 t,判断它们是否是同构的。如果 s 中的字符可以按某种映射关系替换得到 t,那么这两个字符串是同构的。每个出现的字符都应当映射到另一个字符,不改变字符顺序;不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。
- 输入
- s = "egg", t = "add"
- 输出
- true
- 输入
- s = "f11", t = "b23"
- 输出
- false
- 输入
- s = "paper", t = "title"
- 输出
- true
最优解:一步一步想明白
- 3单向映射只能保证“一个 s 字符不分裂成多个 t 字符”,不能保证“多个 s 字符不挤到同一个 t 字符”。
- 4不变量:st 和 ts 始终互相吻合,表示目前读过的字符仍然是一一对应关系。
- 5if len(s) != len(t): return False同构必须逐字符一一对应。长度不同直接 false;这里两个字符串长度相同,继续建立双向映射。
- 6st = {}; ts = {}st 负责检查同一个 s 字符是否稳定;ts 负责检查同一个 t 字符是否只被一个 s 字符使用。
- 7if checks pass: st["p"]="t"; ts["t"]="p"p 还没有映射,t 也没有被占用,所以这一对可以接受。记录两个方向:以后再见 p,必须还是 t;以后再见 t,必须还是 p。
- 8st["a"]="i"; ts["i"]="a"a 和 i 也都没冲突,加入两张表。当前映射是 p->t、a->i。
- 9st["p"] == "t" and ts["t"] == "p"第三对又是 p->t。两张表都能对上,说明重复字符保持了同样的映射。
- 10st["e"]="l"; ts["l"]="e"e 和 l 都是新字符,加入映射表。
- 11st["r"]="e"; ts["e"]="r"这里 t 中的 e 和 s 中的 e 是不同位置、不同方向的字符,不冲突。双向表只要求同一方向内保持一一对应。
- 12return True所有字符对都通过双向检查,所以 paper 和 title 同构。
- 15同构字符串、单词规律、模式匹配,都常用这套双向表检查。
⚠️ 容易写错的地方
✗ 错:只检查 s -> t
✓ 对:同时检查 t -> s
ab -> cc 会被单向映射误判为 true。
✗ 错:看到同名字符就直接判冲突
✓ 对:按方向看映射关系
paper -> title 中,s 的 e 和 t 的 e 出现在不同映射方向,不冲突。
✗ 错:长度不同仍继续扫描
✓ 对:长度不同直接 false
无法逐字符一一对应。
完整代码(Python)
Python
class Solution:
def isIsomorphic(self, s, t):
if len(s) != len(t):
return False
st = {}
ts = {}
for a, b in zip(s, t):
if a in st and st[a] != b:
return False
if b in ts and ts[b] != a:
return False
st[a] = b
ts[b] = a
return True复杂度
时间复杂度
O(n)
同时扫描 s 和 t 一遍。
空间复杂度
O(1)
题目限制为 ASCII 字符,映射表大小有常数上界;若按一般字符集可记为 O(n)。
看不够?换成动画再走一遍
上面的推演每一步都对应一帧动画。点开交互动画版,能一步步看着 同构字符串 的数据怎么变、指针怎么走,还能切 Python / Java / C++ 跟着练。
面试官可能追问
这道题为什么用「哈希表」,换最直接的暴力解会差在哪?+
哈希表抓住了本题的结构特征,把暴力解里重复的工作省掉;暴力解通常要多嵌套一层枚举,数据一大就超时。具体对比见上文「暴力解及其卡点」与「最优解逐步推演」两节。
时间复杂度为什么是 undefined?怎么推出来的?+
按上文复杂度小节的推导,时间复杂度为 undefined。
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。