205. Isomorphic Strings - Explanation
Description
You are given two strings s and t, determine if they are isomorphic.
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 1:
Input: s = "egg", t = "add"
Output: trueExplanation: The strings s and t can be made identical by:
- Mapping 'e' to 'a'.
- Mapping 'g' to 'd'.
Example 2:
Input: s = "foo", t = "bar"
Output: falseExplanation: The strings s and t can not be made identical as 'o' needs to be mapped to both 'a' and 'r'.
Example 3:
Input: s = "paper", t = "title"
Output: trueConstraints:
0 <= s.length == t.length <= 50,000sandtconsist of any valid ascii character.
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- Hash Maps - Storing and looking up key-value pairs in O(1) time
- String Iteration - Traversing characters in a string by index
- Bijective Mapping - Understanding one-to-one correspondence between two sets
1. Hash Map (Two Pass)
Intuition
Two strings are isomorphic if there's a one-to-one mapping between their characters. We need to ensure that each character in s maps to exactly one character in t, and vice versa. A single pass checking only s -> t mapping isn't enough because two different characters in s could map to the same character in t. By running the check twice (once for (s, t) and once for (t, s)), we guarantee the mapping is bijective.
Algorithm
- Create a helper function that checks if characters from one string map consistently to another:
- Use a hash map to store the character mappings.
- For each character, check if an existing mapping conflicts with the current pair.
- Call the helper twice: once with
(s, t)and once with(t, s). - Return
trueonly if both checks pass.
class Solution:
def helper(self, s: str, t: str) -> bool:
mp = {}
for i in range(len(s)):
if (s[i] in mp) and (mp[s[i]] != t[i]):
return False
mp[s[i]] = t[i]
return True
def isIsomorphic(self, s: str, t: str) -> bool:
return self.helper(s, t) and self.helper(t, s)Time & Space Complexity
- Time complexity:
- Space complexity:
Where is the length of the input string and is the number of unique characters in the strings.
2. Hash Map (One Pass)
Intuition
We can verify both mapping directions simultaneously in a single pass. By maintaining two hash maps, one for s -> t and one for t -> s, we check at each position that neither mapping is violated. If a character in s was previously mapped to a different character in t, or if a character in t was previously mapped to a different character in s, the strings aren't isomorphic.
Algorithm
- Create two hash maps:
mapSTfors -> tandmapTSfort -> s. - Iterate through both strings simultaneously:
- If
s[i]already maps to something other thant[i], returnfalse. - If
t[i]already maps to something other thans[i], returnfalse. - Otherwise, record both mappings.
- If
- If the loop completes without conflicts, return
true.
class Solution:
def isIsomorphic(self, s: str, t: str) -> bool:
mapST, mapTS = {}, {}
for i in range(len(s)):
c1, c2 = s[i], t[i]
if ((c1 in mapST and mapST[c1] != c2) or
(c2 in mapTS and mapTS[c2] != c1)):
return False
mapST[c1] = c2
mapTS[c2] = c1
return TrueTime & Space Complexity
- Time complexity:
- Space complexity:
Where is the length of the input string and is the number of unique characters in the strings.
Common Pitfalls
Only Checking One Direction of Mapping
Checking only that each character in s maps to a unique character in t is insufficient. You must also verify the reverse: that each character in t maps to a unique character in s. For example, s = "ab" and t = "aa" would pass a one-way check but fails the bidirectional requirement since both 'a' and 'b' map to 'a'.
Assuming Same Character Sets
The two strings may contain completely different character sets. Do not assume that a character appearing in s must also appear in t, or vice versa. The mapping must be established dynamically as you iterate through both strings.
Sign in to join the discussion