LeetCode 205. 同构字符串
本节目标
用双向映射验证两个等长字符串是否保持一一字符对应关系。
这道题对应单词与映射解题框架的双向映射模型。每个 s 中的字符要稳定映射到 t 中一个字符,同时不同源字符不能汇聚到同一个目标字符。
朴素思路及瓶颈
朴素做法可对每个位置回看所有此前位置,检查“相等关系是否一致”,最坏为 O(n²)。映射把每种字符的历史约束压缩成常数次查表,因此一次扫描就能发现冲突。
双向映射不变量
在处理第 i 对字符前,正向表记录每个已见 s 字符唯一对应的 t 字符,反向表记录相反关系。若正向不一致,说明一个源字符映射到了两个目标;若反向不一致,说明多个源字符映射到了同一目标。只检查正向表会错误接受 badc -> baba 这类多对一关系。
代码实现
C++ 以两个 256 位数组表示字节范围内的双向映射;Python 用两张字典。实现先检查长度,再对每一对字符检查并同步更新两张表。
- C++
- Python
C++17
#include <string>
#include <vector>
using namespace std;
class Solution {
public:
bool isIsomorphic(string s, string t) {
if (s.size() != t.size()) {
return false;
}
vector<int> forward(256, -1);
vector<int> backward(256, -1);
for (size_t index = 0; index < s.size(); index++) {
unsigned char from = static_cast<unsigned char>(s[index]);
unsigned char to = static_cast<unsigned char>(t[index]);
if ((forward[from] != -1 && forward[from] != to) ||
(backward[to] != -1 && backward[to] != from)) {
return false;
}
forward[from] = to;
backward[to] = from;
}
return true;
}
};
Python 3
class Solution:
def isIsomorphic(self, s: str, t: str) -> bool:
if len(s) != len(t):
return False
forward: dict[str, str] = {}
backward: dict[str, str] = {}
for left, right in zip(s, t):
if left in forward and forward[left] != right:
return False
if right in backward and backward[right] != left:
return False
forward[left] = right
backward[right] = left
return True
复杂度分析
- 时间复杂度:
O(n)。 - 空间复杂度:C++ 为
O(1)的固定数组,Python 最坏为O(k),k是不同字符数。
易错点
- 只保存
s -> t,漏掉两个不同字符占用同一个目标字符。 - 字符串长度不同仍按最短长度配对,误把未处理尾部忽略。
- 冲突发生后直接覆盖映射,而没有立即返回失败。
模式迁移
同构判断可迁移到替换密码、模板变量和节点标签的对应检查。若只需判断重复出现的位置模式,也可记录每个符号上次出现的索引并比较索引模式。