When solving string transformation problems, one challenge that often pops up in coding interviews is determining whether two strings are isomorphic. A common string manipulation question tests your understanding of mappings and consistency checks in algorithms.
In this article, we’ll break down the problem, explain the approach, walk through the JavaScript solution, and share some notes to deepen your understanding.
Two strings s
and t
are called isomorphic if the characters in s
can be replaced to get t
. The rules are:
s
must map to one character in t
.s
can map to the same character in t
.In simple terms, it’s a one-to-one mapping problem.
isIsomorphic("egg", "add"); // true
isIsomorphic("foo", "bar"); // false
isIsomorphic("paper", "title"); // true
isIsomorphic("ab", "aa"); // false
To determine if two strings are isomorphic, we need to maintain a consistent mapping between characters from s
to t
and from t
to s
.
Why both directions?
Because just checking one direction (like s -> t
) may allow multiple characters in s
to map to the same character in t
, which violates the one-to-one constraint.
Using character frequency comparison doesn’t work, because two different characters might have the same frequency but map to different positions, which would make the strings not isomorphic.
Map
Here’s the clean, reliable way to solve this using JavaScript’s Map
:
/**
* Determines if two strings are isomorphic.
* @param {string} s - First string
* @param {string} t - Second string
* @return {boolean}
*/
var isIsomorphic = function(s, t) {
if (s.length !== t.length) return false;
const mapST = new Map(); // s → t mapping
const mapTS = new Map(); // t → s mapping
for (let i = 0; i < s.length; i++) {
const c1 = s[i];
const c2 = t[i];
if (mapST.has(c1)) {
if (mapST.get(c1) !== c2) return false;
} else {
mapST.set(c1, c2);
}
if (mapTS.has(c2)) {
if (mapTS.get(c2) !== c1) return false;
} else {
mapTS.set(c2, c1);
}
}
return true;
};
Loop through both strings simultaneously.
For each character in s
and its corresponding character in t
, check if the mapping is already established.
If a mismatch is found in either mapping direction, return false
.
If all characters map consistently, return true
.
✅ Always check both mappings: s → t
and t → s
.
❌ Don’t use frequency counts — they ignore positional integrity.
✅ Use Map
over plain objects in modern JavaScript for more consistent behavior.