1. Two Hash Maps Bijective Mapping
Intuition
Maintain s2t and t2s hash maps. For index i from 0 to n - 1: let c1 = s[i] and c2 = t[i]. If c1 is in s2t and s2t[c1] != c2, return false. If c2 is in t2s and t2s[c2] != c1, return false. Otherwise, record s2t[c1] = c2 and t2s[c2] = c1. If all characters process without conflict, return true.
When to apply: The most clear explanation of the mathematical definition of bijection.
Algorithm
- Create two maps:
mapSandmapT. - Loop
ifrom 0 ton - 1: - If
mapS.has(s[i])andmapS.get(s[i]) != t[i], return false. - If
mapT.has(t[i])andmapT.get(t[i]) != s[i], return false. - Record
mapS.set(s[i], t[i])andmapT.set(t[i], s[i]). - Return true.
Two Hash Maps Bijective Mapping Verification Trace
2 of 2 questions left todayObservation: At index 0: s[0]='e' and t[0]='a'
Observation: At index 0: s[0]='e' and t[0]='a'.
Decision: Neither character has been mapped yet. Set forward mapping 'e' -> 'a' and reverse mapping 'a' -> 'e'.
Invariant: Bijective 1-to-1 correspondence established for first character pair.
#include <iostream>#include <string>#include <unordered_map> class Solution {public: bool isIsomorphic(std::string s, std::string t) { if (s.size() != t.size()) return false; std::unordered_map<char, char> s2t, t2s; for (int i = 0; i < (int)s.size(); ++i) { char c1 = s[i], c2 = t[i]; if (s2t.count(c1) && s2t[c1] != c2) return false; if (t2s.count(c2) && t2s[c2] != c1) return false; s2t[c1] = c2; t2s[c2] = c1; } return true; }}; int main() { Solution sol; std::cout << (sol.isIsomorphic("egg", "add") ? "true" : "false") << std::endl; // true std::cout << (sol.isIsomorphic("foo", "bar") ? "true" : "false") << std::endl; // false return 0;}Time & Space Complexity
- Time complexity:
O(N)— Single linear pass with constant-time hash map lookups. - Space complexity:
O(K) where K <= 256 unique characters
Why Brute Force Doesn't Scale:
Two static 256-int arrays eliminate all hashing overhead.
Stack allocation of 512 integers has zero garbage collection overhead.