给定两个字符串 s
和 t
,判断它们是否是同构的。
如果 s
中的字符可以按某种映射关系替换得到 t
,那么这两个字符串是同构的。
每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。
简单来说题目仅允许一对一的映射,一对多和多对一是不允许的。所以我们需要在判别的时候分别引入一对多和多对一的判别。
我们先把框架搭好:
class Solution {
public:
bool isIsomorphic(std::string s, std::string t)
{
std::unordered_map<char, char> s2t;
std::unordered_map<char, char> t2s;
int length = s.size();
for (int i = 0; i < length; i++)
{
//将要写入判别多对一和一对多映射的代码
}
return true;
}
};
我们创建了两个哈希表:一个是s2t,表示s到t的映射,其键是s,值是t
另一个是t2s,表示t到s的映射,其键是t,值是s
那一对多和多对一的映射判断要怎么写呢,我们单从一对多来看,当我们写出来一对多的判断情况,多对一的判断也就水到渠成了。
我先把代码贴出来,然后再看着代码一点点解释:
s2t.find(s[i]) != s2t.end() && s2t[s[i]] != t[i]
这个代码是什么意思,我们庖丁解牛:.find()成员函数是用于搜索容器中的某个元素,在哈希表中表现为搜索键,如果寻到目标键,返回指向该键的迭代器,如果没有找到,返回该容器的end()。
所以&&前面的判断就是判断s2t中是否能找到s字符中的第i个字符,我们把他称之为X,其映射我们称之为Y1。那么右边的就是判断s2t这个哈希表内的键为X的字符映射Y1和此时t字符串中映射位置的字符Y2是否相等,如果相等,自然而然是一对一的映射,因为至少从目前来看X全部映射到Y1上。
但是如果映射出来是Y2,也就是不相等,那么说明s中的字符X映射到t中有Y1和Y2两个映射,就是一对多。
因此我们就可以写出来for循环之中的语句:
class Solution {
public:
bool isIsomorphic(std::string s, std::string t)
{
std::unordered_map<char, char> s2t;
std::unordered_map<char, char> t2s;
int length = s.size();
for (int i = 0; i < length; i++)
{
//如果存在一对多或多对一映射
//具体:1.在s->t的映射中找到了有该字母的映射,而原有s2t中的映射对应t中的映射并非此时t的值,即一对多
// 2.t->s的映射中找到了该字母的映射,而原有t2s的映射中对应的s并非此时s的值,即多对一
if (s2t.find(s[i]) != s2t.end() && s2t[s[i]] != t[i] ||
t2s.find(t[i]) != t2s.end() && t2s[t[i]] != s[i])
return false;
s2t[s[i]] = t[i];
t2s[t[i]] = s[i];
}
return true;
}
};
如果检测一对多和多对一,那么对着来写就可以了