LeetCode 205. 同构字符串
📌 题目描述
题目级别:简单
给定两个字符串 s 和 t ,判断它们是否是同构的。
如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。
每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。
- 示例 1:
输入:s = "egg",t = "add"
输出:true - 示例 2:
输入:s = "foo",t = "bar"
输出:false
💡 破题思路:双向绑定 (Bidirectional Mapping)
这道题的核心陷阱在于:映射必须是一对一的 (One-to-One) 。
不仅 s 中的一个字符不能映射到 t 中的两个不同字符,t 中的一个字符也不能被 s 中的两个不同字符映射。
-
错误示范(单向映射) :如果只验证
s -> t,对于s="foo",t="bar",扫描到第二个o时,发现o已经映射了a,现在的对应关系却是o->r,发生冲突,正确返回false。但对于s="badc",t="baba",s里的每个字母都映射向了单一目标,但t里的b却同时被b和d映射(多对一),这就漏判了! -
正确做法(双向哈希表) :
我们需要准备两个字典:
mp记录s[i] -> t[i],pm记录t[i] -> s[i]。遍历字符串时,只要发现
mp中s[i]的既有记录不等于当前的t[i],或者pm中t[i]的既有记录不等于当前的s[i],立刻判定为伪同构,触发防御机制返回false。
💻 C++ 代码实现 (原汁原味作者版)
cpp
class Solution {
public:
bool isIsomorphic(string s, string t) {
// 定义两个 map,实现严格的双向绑定
map<char, char> mp, pm;
int n = s.size();
for (int i = 0; i < n; i ++ )
{
// 巧用 C++ map 特性:未初始化的 char 默认值为 0 ('\0')
// 如果 s[i] 已经有归宿,且归宿不是现在的 t[i],直接判定失败
if (mp[s[i]] != 0 && mp[s[i]] != t[i]) return false;
// 如果 t[i] 已经有归宿,且归宿不是现在的 s[i],说明被别人绿了,判定失败
if (pm[t[i]] != 0 && pm[t[i]] != s[i]) return false;
// 确立双向恋爱关系
mp[s[i]] = t[i], pm[t[i]] = s[i];
}
return true;
}
};