给定两个字符串 s 和 t,判断它们是否是同构的。如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的。所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。两个字符不能映射到同一个字符上,但字符可以映射自己本身。
1. 用两个map分别记录当前位置字符第一次出现的位置
bool isIsomorphic(string s, string t) {
map<char,int> a1;
map<char,int> b1;
string one;
string two;
for (int i = 0; i < s.size(); i++)
{
if (a1.count(s[i])==0) a1[s[i]]=i;
one += to_string(a1[s[i]]);
if (b1.count(t[i])==0) b1[t[i]]=i;
two += to_string(b1[t[i]]);
}
return (one==two)?1:0;
}
2. 利用find查找对比两个字符串对应位置的字符在字符串内第一次出现的位置
bool isIsomorphic(string s, string t) {
int len=s.size();
for(int i=0; i<len; i++){
if(s.find(s[i]) != t.find(t[i])) return false;
}
return true;
}
3. 用哈希表记录。如果a中第一次记录下的b中对应的单词与第二次出现a时对应的单词不同则说明两字符串非同构。同时为了防止b中的字符全部相同导致的错误,需要进行两组遍历互锁。
1)利用数组实现哈希表
bool isIsomorphic(string s, string t) {
int len = s.size();
int as[128]={0}, at[128]={0}; //哈希表
for(int i=0; i<len; i++){
if(as[(int)s[i]]==0){
as[(int)s[i]] = t[i];
}
else if(as[(int)s[i]]!=t[i]){
return false;
}
if(at[(int)t[i]]==0){
at[(int)t[i]] = s[i];
}
else if(at[(int)t[i]]!=s[i]){
return false;
}
}
return true;
}
2)用map实现哈希表
bool isIsomorphic(string s, string t) {
unordered_map<char,char> smap;
unordered_map<char,char> tmap;
for(int i = 0; s[i] != '\0'; ++ i){
char ss = s[i];
char tt = t[i];
if(smap.count(ss)){
if(smap[ss] != tt) return false;
}
else if(tmap.count(tt)){
if(tmap[tt] != ss) return false;
}
else{
smap[ss] = tt;
tmap[tt] = ss;
}
}
return true;
}
4. Map和set配合解题,set用来防止abb,aaa这类情况,当然这个set也可用string替代(解法1)
bool isIsomorphic(string s, string t) {
unordered_map<char, char> record;
unordered_set<char> mapped; // 用于记录字符串 t 中已经被映射过了的字符
for (int i = 0; i < s.size(); i++) {
if (record.find(s[i]) == record.end()) { // 当前字符s[i]第一次出现时,则 '尝试' 为其建立映射,但不一定会成功
if (mapped.find(t[i]) == mapped.end()) { // s[i]想要映射到t[i],并且t[i]没有被别人映射过
record[s[i]] = t[i]; // s[i] ---> t[i]
mapped.insert(t[i]); // 标记t[i]为已被映射过的字符
} else // 当前字符s[i]想要映射到的那个字符t[i],已经被别的字符映射过了
return false;
} else { // s[i] 之前已经建立过了映射
if (t[i] != record[s[i]])
return false;
}
}
return true;
}