题目描述:
给定两个字符串 s 和 t,判断它们是否是同构的。
如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的。
所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。两个字符不能映射到同一个字符上,但字符可以映射自己本身。
示例 1:
输入: s = "egg", t = "add" 输出: true
示例 2:
输入: s = "foo", t = "bar" 输出: false
示例 3:
输入: s = "paper", t = "title" 输出: true
说明:
你可以假设 s 和 t 具有相同的长度。
本题思路有两种,都是用map来操作,保存相应字符,进行操作
第一种:用一个map保存两个字符串中的字符,令键为第一个字符串中的字符,值为第二字符串中的字符,然后进行判断,遍历第二个字符串,当第二个字符串中的字符不在map中能找到,就返回false,证明不是同构字符串,当都相等时,则是同构字符串。这个地方有一个问题,就是会出现多对一的映射,这种映射肯定不是同构字符串,例如,ab,aa这两个字符串,判断是,总能在map中找到第二个字符串中的字符,返回true,这样就出错了,怎么解决这个问题呢,同set,保存当作值添加进map中的第二个字符串的字符,当再次遇到这个字符(也就是set中已经存在了这个字符,证明,这就产生多对一的映射了,这样不合理,返回false),这样就可以满足所有情况了。
第二种思路:这个很好理解,我觉得这个是比第一个还要简单的方法,不过时间复杂度能比第一个高一点。这个方法就是用两个map,一个map保存第一个字符串中字符与第二个字符串中的字符的映射,第二个map保存第二个字符串和第一个字符串的映射,然后遍历任意字符串长度(因为两个字符串相同),判断第一个字符串在第二个map中是否存在或者第二个字符串在第一个map中是否存在,任意一个不存在则返回false,最后遍历完后返回true.
第一种思路代码:
public static void main(String[] args){
// 使用一个哈希表map维护两个字符串中字符的映射关系,同时用一个set保存映射的值
String s = "ad";
String t = "aa";
char []ch1 =s.toCharArray ();
char []ch2 =t.toCharArray ();
// map映射用来存储第一个字符串中的字符与第二个字符串中的字符(键:第一个字符串中的字符,值:第二个字符串中的字符)
Map<Character,Character> map = new HashMap <> ( );
// 用来去重,(当多对一的映射时,用这个处理,例如第一个字符串有两个不一样的字符,第二个字符串一样的字符,这样就形成了多对一。不是同构字符串)
Set<Character> set = new HashSet <> ( );
for (int i = 0;i<ch1.length;i++){
// 当map中有ch1中的字符时,判断ch2中的字符是否等于,map中ch1对应字符的值,如果不等与,则不是同构字符串
if (map.containsKey ( ch1[i] )){
if (ch2[i]!=map.get ( ch1[i] )){
System.out.println("不是同构字符串");
break;
}
// 如果map没有ch1中字符对应的键
}else{
// 然后判断集合中是否存在ch2中的字符,存在时,证明map中的键与值形成多对1的关系,也就是,map中的键不一致但值是一样的,当然不是同构字符串.
if (set.contains ( ch2[i] )){
System.out.println("不是同构字符串");
break;
}else {
// 如果键不存在,并且,值也不一样,这样就将map,ch1做键,ch2做值,放到map中,并且将ch2的字符添加到set,用来判断是否存在一对多的隐射.
map.put ( ch1[i],ch2[i] );
set.add ( ch2[i] );
}
}
}
System.out.println("是同构字符串");
执行结果:
执行用时:
第二中思路代码:
第二种方法
//用两个map分别保存1-2,2-1的映射,然后判断值是否存在与各个映射中
Map<Character,Character> map1 = new HashMap <> ( );
Map<Character,Character> map2 = new HashMap <> ( );
for(int i=0;i<ch1.length;i++){
map1.put ( ch1[i],ch2[i] );
}
for (int i = 0;i<ch2.length;i++){
map2.put ( ch2[i],ch1[i] );
}
for (int j = 0;j<ch2.length;j++){
if (ch1[j]!=map2.get ( ch2[j] )||ch2[j]!=map1.get ( ch1[j] )){
System.out.println("不是同构字符串");
break;
}
}
System.out.println("是同构字符串");
执行用时:
总结:这道题还是map的使用,个人觉得两个map好用,好理解,map和set灵活,时间复杂度低,不太好理解,map重点一定是定住各个映射,别映射错了。
2019-3-19