Isomorphic Strings
Given two strings stst
Example 1
Output: true
Explanation: e → a, g → d.
Example 2
Output: false
Explanation: o would have to become both a and r.
Example 3
Output: true
How to Think About It
Step 1: The mapping must work in both directions
Two things can break it:
- one character of
paired with two different characters ofs ("foo" and "bar": o pairs with a and r);t - two characters of
paired with the same character ofs ("ab" and "cc": a and b both pair with c).t
A single map from st
Step 2: A neater check with last positions
Two strings are isomorphic exactly when, at every index is[i]t[i]
Store lastS[c]lastT[c]ilastS[s[i]]lastT[t[i]]i + 1
Walkthrough
s = "badc"t = "baba"
| i | s[i], t[i] | lastS[s[i]] | lastT[t[i]] | Same? |
|---|---|---|---|---|
| 0 | b, b | 0 (never) | 0 (never) | yes |
| 1 | a, a | 0 | 0 | yes |
| 2 | d, b | 0 (d is new) | 1 (b at index 0) | no: return false |
d and b would both have to map to b, which is not allowed.
Java Solution
Arrays of 256 entries cover every ASCII character, as the problem allows.
import java.util.Arrays;
public class IsomorphicStrings {
public static boolean isIsomorphic(String s, String t) {
if (s.length() != t.length()) {
return false;
}
// last position (+1) where each character was seen; 0 means "not seen yet"
int[] lastS = new int[256];
int[] lastT = new int[256];
for (int i = 0; i < s.length(); i++) {
char a = s.charAt(i);
char b = t.charAt(i);
if (lastS[a] != lastT[b]) {
return false; // a and b were last paired differently
}
lastS[a] = i + 1;
lastT[b] = i + 1;
}
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("badc", "baba")); // false
}
}
The original implementation,
Complexity
- Time: O(n).
- Space: O(1): two fixed arrays.
The same two-way check, applied to letters and words, is