给定两个字符串 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 字符组成
每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。
不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。
题干中的这两句话,表示的是s
字符串中的每一个字符与t
字符串中的每一个字符是唯一的映射关系(但不是一一对应的关系,比如:a->b, e->a,s
字符串中的每一个字符都映射到t
字符串中的不同字符)。且顺序要不变,比如:假设存在这个(a->b, e->a)映射关系,那么"aeeae"对应的t
字符串必须是"baaba"。(理解题意对我来说是此题的难点)
因此,我们需要构造两个hash散列,长度均为128(因为字符是所有可见的ASCII字符),第一个hash散列存放的是从s
字符串到t
字符串的映射关系,它的键值key(也就是下标)代表的是s
字符串中字符的ASCII码,值value(也就是hash[i])存放的是对应的t
字符串中字符的ASCII码。第二个hash散列存放的是t
字符串中各个字符是否被对应,它的键值key(也就是下标)代表的是t
字符串中字符的ASCII码,值value可以用0或者1表示是否被占用。
遍历s
字符串,如果遍历到的字符s.charAt(i)
没有映射关系且对应的t.charAt(i)
也没有被占用,这个映射关系将被存入hash散列;如果遍历到的字符s.charAt(i)
有映射关系,那么核对当前字符的映射是否和t.charAt(i)
一致,如果不一致,输出false
。直接结束遍历,则输出true
。
class Solution {
public boolean isIsomorphic(String s, String t) {
int []hash = new int[128]; //key是s中字母的ASCII码,value是s映射到的t中字母ASCII码
int []used = new int[128]; //显示t中字母是否被匹配掉了
int i;
int L = s.length(); //只需判断一个,因为t.length == s.length
for (i=0;i<128;i++) {//初始化
hash[i] = -1;
used[i] = 0; //表示t字符串中该字母没有被使用
}
for (i=0;i<L;i++) {
if (hash[s.charAt(i)]==-1 && used[t.charAt(i)]==0) {//表示还未匹配
hash[s.charAt(i)] = (int)(t.charAt(i)); //匹配(注意是双向的!)
used[t.charAt(i)] = 1;
}
else{ //匹配过的
if (hash[s.charAt(i)]!=-1 && hash[s.charAt(i)]==t.charAt(i)) //匹配正确
continue;
else
return false;
}
}
return true;
}
}