Given two strings s and t, determine if they are isomorphic.
Two strings are isomorphic if the characters in s can be replaced to get t.
All occurrences of a character must be replaced with another character while preserving the order of characters. No two characters may map to the same character but a character may map to itself.
Example 1:
Input: s ="egg",
t ="add"
Output: true
Example 2:
Input: s ="foo",
t ="bar"
Output: false
Example 3:
Input: s ="paper",
t ="title"
Output: true
Note:
You may assume both s and t have the same length.
思路1(用两个map)
1. scan char a from S and char b from T in the same time
2. use two int array to mimic hash table: mapAB, mapBA
3. if mapAB[a] == 0 , means I didn't mapping it, assign current b to mapAB[a]
otherwise, means I did mapping it, check b == mapAB[a] ?
4. do the same operation for mapBA
5. why checking two maps at the same time? Coz S: egg -> T: aaa return true
then we still check T: aaa -> S: egg
代码
1 class Solution { 2 public boolean isIsomorphic(String s, String t) { 3 if(s.length()!=t.length()) return false; 4 // uses the arrays to mimic two hash table 5 int [] mapAB = new int[256];//ASCII characters 6 int [] mapBA = new int[256]; 7 for(int i = 0; i< s.length();i++){ 8 char a = s.charAt(i); 9 char b = t.charAt(i); 10 // mapAB[a]!=0 means I already mapping it 11 if(mapAB[a]!=0){ 12 if(mapAB[a]!=b) return false; 13 } 14 // mapAB[a]==0 means I haven't mapping it 15 else{ 16 mapAB[a]= b; 17 } 18 19 // why checking two map? coz S:egg T: aaa would return true if only checking mapAB 20 if(mapBA[b]!=0){ 21 if(mapBA[b]!=a) return false; 22 }else{ 23 mapBA[b] = a; 24 } 25 } 26 return true; 27 } 28 }
思路2(只用一个map)
1. scan either S or T(assuming they have same length)
2. store the idx of current char in both strings.
if previously stored idx are different from current idx, return false
举例:
S: egg T: aaa
m[e] = 1 m[a+256] = 1
m[g] = 2 occurs that previous m[a+256] = 1 return false
代码
1 class Solution { 2 public boolean isIsomorphic(String s, String t) { 3 if(s.length() != t.length()) return false; 4 int[] m = new int[512]; 5 for (int i = 0; i < s.length(); i++) { 6 if (m[s.charAt(i)] != m[t.charAt(i)+256]) return false; 7 m[s.charAt(i)] = m[t.charAt(i)+256] = i+1; 8 } 9 return true; 10 } 11 } 12 13 /* Why not m[s.charAt(i)] = m[t.charAt(i)+256] = i ? 14 coz 0 is the default value, we should not use it. otherwise we cannot distinguish between 15 the default maker and the the marker we made. 16 S: aa T: ab 17 i= 0: m[a] = 0 m[a+256] = 0 18 but m[b+256] is defaulted 0 19 20 */
followup1:
如果输入K个string,判断其中至少两个是Isomorphic Strings, 返回boolean
思路
1. 将所有的given string都转成同一种pattern
ex. foo -> abb
ex. gjk -> abc
ex. pkk -> abb
2. 用一个hashmap来存 transfered word 和其出现的频率。
key : value(frequency)
ex. foo -> abb : 1
ex. gjk -> abc : 1
ex. pkk -> abb : 1+1 return true
代码
1 public boolean findIsomorphic(String[] input) { 2 // key: transWord, value: its corresponding frequency 3 Map<String, Integer> map = new HashMap<>(); 4 for (String s : input) { 5 // transfer each String into same pattern 6 String transWord = transfer(s); 7 if (!map.containsKey(transWord)) { 8 map.put(transWord, 1); 9 } 10 // such transWord pattern already in String[] 11 else { 12 return true; 13 } 14 } 15 return false; 16 } 17 18 /* pattern: every word start with 'a' 19 when comes a new letter, map it to cur char, 20 and increase the value of cur cha 21 */ 22 private String transfer(String word) { 23 Map<Character, Character> map = new HashMap<>(); 24 StringBuilder sb = new StringBuilder(); 25 char cur = 'a'; 26 for (char letter : word.toCharArray()) { 27 if (!map.containsKey(letter)) { 28 map.put(letter, cur); 29 cur++; 30 } 31 sb.append(map.get(letter)); 32 } 33 return sb.toString(); 34 }
followup2:
如果输入K个string, 判断其中任意两两是Isomorphic Strings,返回boolean
即给定K个string都能化成同一种等值的pattern