给定两个字符串 s
和 t
,判断它们是否是同构的。
如果 s
中的字符可以按某种映射关系替换得到 t
,那么这两个字符串是同构的。
每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。
示例 1:
输入:s ="egg"
, t ="add"
输出:true
示例 2:
输入:s ="foo"
, t ="bar"
输出:false
示例 3:
输入:s ="paper"
, t ="title"
输出:true
提示:
1 <= s.length <= 5 * 104
t.length == s.length
s
和t
由任意有效的 ASCII 字符组成
解法一:
class Solution {
public:
bool isIsomorphic(string s, string t) {
int n1 = s.size(), n2 = t.size();
if (n1 != n2) // 如果两个字符串长度不相同,直接返回 false
return false;
unordered_map<char, vector<int>> smap, tmap;
for (int i = 0; i < n1; i++) {
smap[s[i]].push_back(i); // 记录 s 中每个字符出现的索引
tmap[t[i]].push_back(i); // 记录 t 中每个字符出现的索引
}
// 检查两个字符串中的字符索引序列是否相同
for (int i = 0; i < n1; i++) {
if (smap[s[i]] != tmap[t[i]]) // 如果索引序列不相同,返回 false
return false;
}
return true; // 如果所有字符的索引序列都相同,则字符串是同构的
}
};
如果两个字符串的长度不相等,那么肯定不满足同构,直接返回假。创建一个哈希表,分别用来存储s和t各个字符出现的索引,用for循环遍历两个字符串,将索引填入哈希表中。然后检查两个哈希表中字符串的索引序列是否相同,如果有不同则直接返回假,全部比对完之后返回真。
解法二:
class Solution {
public:
bool isIsomorphic(string s, string t) {
// 创建两个无序映射,用于存储字符串 s 和 t 的字符映射关系
unordered_map<char, char> s2t;
unordered_map<char, char> t2s;
// 获取字符串 s 的长度,假设 s 和 t 的长度相同
int len = s.length();
// 遍历字符串 s 和 t 的每个字符
for (int i = 0; i < len; ++i) {
char x = s[i], y = t[i]; // 获取当前位置的字符
// 检查 s2t 中是否已经有 x 的映射,并且映射的字符不是 y
// 或者 t2s 中已经有 y 的映射,并且映射的字符不是 x
// 如果两个条件中任意一个为真,说明 s 和 t 不是同构的
if ((s2t.count(x) && s2t[x] != y) || (t2s.count(y) && t2s[y] != x)) {
return false;
}
// 更新 s2t 和 t2s 的映射关系
s2t[x] = y;
t2s[y] = x;
}
// 如果循环完成,说明 s 和 t 是同构的
return true;
}
};
这段代码的思路是判断两个字符串 s 和 t 是否是同构的。
首先,创建了两个无序映射 unordered_map,分别是 s2t 和 t2s,用于存储字符的映射关系。s2t 存储 s 到 t 的映射,t2s 存储 t 到 s 的映射。
然后,获取字符串 s 的长度,假设 s 和 t 的长度相同。
接下来,使用一个循环遍历字符串 s 和 t 的每个字符。在循环中,分别获取当前位置的字符 x 和 y。
然后,检查 s2t 中是否已经存在字符 x 的映射,并且映射的字符不是 y。或者 t2s 中已经存在字符 y 的映射,并且映射的字符不是 x。如果任意一个条件为真,说明 s 和 t 不是同构的,直接返回 false。
如果没有返回 false,则更新 s2t 和 t2s 的映射关系,将 x 映射为 y,将 y 映射为 x。
最后,如果循环完成,说明 s 和 t 是同构的,返回 true。
整体思路就是通过两个映射来记录 s 和 t 的字符之间的对应关系,然后判断对应关系是否满足同构的条件。