题目来源
题目描述
题目解析
方法一
两个字符串同构的含义就是字符串s
可以唯一的映射到t
,同时t
也可以唯一元素到s
。举个例子:
egg 和 add 同构,就意味着下边的映射成立
e -> a
g -> d
也就是将 egg 的 e 换成 a, g 换成 d, 就变成了 add
同时倒过来也成立
a -> e
d -> g
也就是将 add 的 a 换成 e, d 换成 g, 就变成了 egg
foo 和 bar 不同构,原因就是映射不唯一
o -> a
o -> r
其中 o 映射到了两个字母
我们可以利用一个map
来处理映射。 对于s
到t
的映射,我们同时遍历s
和t
,假设当前遇到的字母分别是c1
和c2
- 如果
map[c1]
不存在,那么就将c1
映射到c2
,即map[c1] = c2
- 如果
map[c1]
存在,那么就判断map[c1]
是否等于c2
,也就是映射之前的映射是否和当前的映射相同
注意,我们需要映射两个方向,只验证一个方向是不可以的。比如
"badc"
"baba"
class Solution {
public:
bool helper(string s, string t){
if(s.size() != t.size()){
return false;
}
std::map<char, char> mapper;
for (int i = 0; i < s.size(); ++i) {
char ch1 = s[i];
char ch2 = t[i];
if(mapper.count(ch1)){
if(mapper[ch1] != ch2){
return false;
}
}else{
mapper[ch1] = ch2;
}
}
return true;
}
bool isIsomorphic(string s, string t) {
return helper(s, t) && helper(t, s);
}
};
方法2
解法一中,我们判断 s 和 t 是否一一对应,通过对两个方向分别考虑来解决的。
这里的话,我们找一个第三方来解决,即,按照字母出现的顺序,把两个字符串都映射到另一个集合中。
举个现实生活中的例子,一个人说中文,一个人说法语,怎么判断他们说的是一个意思呢?把中文翻译成英语,把法语也翻译成英语,然后看最后的英语是否相同即可。
将第一个出现的字母映射成 1,第二个出现的字母映射成 2
对于 egg
e -> 1
g -> 2
也就是将 egg 的 e 换成 1, g 换成 2, 就变成了 122
对于 add
a -> 1
d -> 2
也就是将 add 的 a 换成 1, d 换成 2, 就变成了 122
egg -> 122, add -> 122
都变成了 122,所以两个字符串异构。
因为 0 是我们的默认值,所以不能直接赋值为下标,而是「下标加 1」。
std::string helper(std::string& s){
int cnt = 1;
std::string str;
std::map<char, int> mapper;
for (int i = 0; i < s.size(); ++i) {
char ch = s[i];
if(!mapper.count(ch)){
mapper[ch] = cnt++;
}
str += std::to_string(mapper[ch]);
}
return str;
}
bool isIsomorphic(string s, string t) {
return helper(s) == helper(t);
}
其实我们不需要将字符串完全转换,我们可以用两个 map 分别记录两个字符串每个字母的映射。将所有字母初始都映射到 0。记录过程中,如果发现了当前映射不一致,就可以立即返回 false 了。
举个例子:
对 abaddee 和 cdbccff
a b a d d e e
c d b c c f f
^
当前
a -> 0
c -> 0
修改映射
a -> 1
c -> 1
a b a d d e e
c d b c c f f
^
当前
b -> 0
d -> 0
修改映射
b -> 2
d -> 2
a b a d d e e
c d b c c f f
^
当前
a -> 1 (之前被修改过)
b -> 0
出现不一致,所以两个字符串不异构
代码如下:
bool isIsomorphic(string s, string t) {
if(s.size() != t.size()){
return false;
}
std::vector<int> mapper1(128, 0), mapper2(128, 0);
for (int i = 0; i < s.size(); ++i) {
char ch1 = s[i];
char ch2 = t[i];
if(mapper1[ch1] != mapper2[ch2]){
return false;
}else{
//是否已经修改过,修改过就不需要再处理
if(mapper1[ch1] == 0){
mapper1[ch1] = i + 1;
mapper2[ch2] = i + 1;
}
}
}
return true;
}
类似题目
题目 | 思路 |
---|---|
leetcode:205. 同构字符串 Isomorphic Strings | |
leetcode:290. 单词规律 Word Pattern |