Problem
Given two strings s and t, determine if they are isomorphic.
Definition
Two strings s
and t
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
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
Solution
Note, isomorphic mapping is both ways, i.e. in foo and bar; f maps to b but b also maps to f. Lets look at example.
Suppose, we have s as foot
and t as baab
. If we use 1 map, we have following map
a --> b
p --> a
p --> a // p already exists in map, map.get(s[i]) == t[i]
l --> b
e --> c
If we just check $s[i]$ matching $t[i]$ (without matching $t[i]$ back to $s[i]$ ) we will see that both strings are isomorphic, but that is incorrect. The reason is both a
and l
mapped to b
.
Method 1 - Using 1 Hashmap ❌
We can define a map which tracks the char-char mappings. If a value is already mapped, it can not be mapped again.
Time complexity O(n^2) by mistake:
public boolean isIsomorphic(String s, String t) {
if (s == null && t == null)
return true;
else if (s == null || t == null){
return false;
}
if (s.length() != t.length())
return false;
Map<Character, Character> map = new HashMap<> ();
for (int i = 0; i<s.length(); i++) {
char c1 = s.charAt(i);
char c2 = t.charAt(i);
if (map.containsKey(c1)) {
if (map.get(c1) != c2) // if not consistant with previous ones
return false;
} else {
if (map.containsValue(c2)) //if c2 is already being mapped. Time complexity O(n) here
return false;
map.put(c1, c2);
}
}
return true;
}
- Time complexity:
O(n^2)
(ascontainsValue
take O(n) and as it is nested under loop, it is O(n^2)) - Space complexity:
O(n)
Method 2 - Using 2 Hashmaps 🏆
public boolean isIsomorphic(String s, String t) {
if (s.length() != t.length()) {
return false;
}
Map<Character, Character> first = new HashMap<>();
Map<Character, Character> second = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
char d = t.charAt(i);
if (first.containsKey(c)) {
char dStored = first.get(c);
if (d != dStored) {
return false;
}
} else {
first.put(c, d);
if (second.containsKey(d)) {
return false;
}
second.put(d, c);
}
}
return true;
}
- Time complexity:
O(n)
- Space complexity:
O(n)