🧠
Optimal Bidirectional Hash Map Mapping
💡 This approach ensures a one-to-one mapping by maintaining two hash maps, one from s to t and another from t to s, guaranteeing no two characters map to the same character.
Intuition
Track mappings in both directions simultaneously to ensure uniqueness and consistency.
Algorithm
- If lengths differ, return false immediately.
- Create two hash maps: s_to_t and t_to_s.
- Iterate through characters of s and t simultaneously.
- For each pair, check if mappings exist and are consistent in both maps.
- If any inconsistency is found, return false.
- If all pairs are consistent, return true.
💡 This algorithm is the most robust and efficient, ensuring no conflicting mappings in either direction.
def isIsomorphic(s: str, t: str) -> bool:
if len(s) != len(t):
return False
s_to_t = {}
t_to_s = {}
for c1, c2 in zip(s, t):
if c1 in s_to_t:
if s_to_t[c1] != c2:
return False
else:
s_to_t[c1] = c2
if c2 in t_to_s:
if t_to_s[c2] != c1:
return False
else:
t_to_s[c2] = c1
return True
# Driver code
if __name__ == "__main__":
print(isIsomorphic("egg", "add")) # True
print(isIsomorphic("foo", "bar")) # False
print(isIsomorphic("paper", "title")) # True
print(isIsomorphic("ab", "aa")) # False
Line Notes
if len(s) != len(t):Early exit for length mismatch
s_to_t = {}Map from s characters to t characters
t_to_s = {}Map from t characters to s characters
if c1 in s_to_t:Check existing mapping from s to t for consistency
import java.util.*;
public class Solution {
public static boolean isIsomorphic(String s, String t) {
if (s.length() != t.length()) return false;
Map<Character, Character> sToT = new HashMap<>();
Map<Character, Character> tToS = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
char c1 = s.charAt(i), c2 = t.charAt(i);
if (sToT.containsKey(c1)) {
if (sToT.get(c1) != c2) return false;
} else {
sToT.put(c1, c2);
}
if (tToS.containsKey(c2)) {
if (tToS.get(c2) != c1) return false;
} else {
tToS.put(c2, c1);
}
}
return true;
}
public static void main(String[] args) {
System.out.println(isIsomorphic("egg", "add")); // true
System.out.println(isIsomorphic("foo", "bar")); // false
System.out.println(isIsomorphic("paper", "title")); // true
System.out.println(isIsomorphic("ab", "aa")); // false
}
}
Line Notes
if (s.length() != t.length())Length check to avoid unnecessary processing
Map<Character, Character> sToT = new HashMap<>();Map s->t characters
Map<Character, Character> tToS = new HashMap<>();Map t->s characters
if (sToT.containsKey(c1))Check if s character already mapped to a consistent t character
#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;
bool isIsomorphic(string s, string t) {
if (s.length() != t.length()) return false;
unordered_map<char, char> sToT, tToS;
for (int i = 0; i < s.length(); i++) {
char c1 = s[i], c2 = t[i];
if (sToT.count(c1)) {
if (sToT[c1] != c2) return false;
} else {
sToT[c1] = c2;
}
if (tToS.count(c2)) {
if (tToS[c2] != c1) return false;
} else {
tToS[c2] = c1;
}
}
return true;
}
int main() {
cout << boolalpha << isIsomorphic("egg", "add") << endl; // true
cout << boolalpha << isIsomorphic("foo", "bar") << endl; // false
cout << boolalpha << isIsomorphic("paper", "title") << endl; // true
cout << boolalpha << isIsomorphic("ab", "aa") << endl; // false
return 0;
}
Line Notes
if (s.length() != t.length())Length mismatch check
unordered_map<char, char> sToT, tToS;Two maps for bidirectional character mapping
if (sToT.count(c1))Check if s character already mapped to a consistent t character
if (tToS.count(c2))Check if t character already mapped to a consistent s character
function isIsomorphic(s, t) {
if (s.length !== t.length) return false;
const sToT = new Map();
const tToS = new Map();
for (let i = 0; i < s.length; i++) {
const c1 = s[i], c2 = t[i];
if (sToT.has(c1)) {
if (sToT.get(c1) !== c2) return false;
} else {
sToT.set(c1, c2);
}
if (tToS.has(c2)) {
if (tToS.get(c2) !== c1) return false;
} else {
tToS.set(c2, c1);
}
}
return true;
}
// Test cases
console.log(isIsomorphic("egg", "add")); // true
console.log(isIsomorphic("foo", "bar")); // false
console.log(isIsomorphic("paper", "title")); // true
console.log(isIsomorphic("ab", "aa")); // false
Line Notes
if (s.length !== t.length)Early exit for length mismatch
const sToT = new Map();Map s->t characters
const tToS = new Map();Map t->s characters
if (sToT.has(c1))Check if s character already mapped to consistent t character
Single pass with constant-time map lookups and insertions
💡 For n=1000, this approach performs about 1000 operations, efficient for large inputs
Interview Verdict: Accepted - optimal solution
This approach is the best balance of correctness and efficiency, suitable for interviews.