LeetCode – Isomorphic Strings (Java)

Given two strings s and t, determine if they are isomorphic. Two strings are isomorphic if the characters in s can be replaced to get t.

For example,"egg" and "add" are isomorphic, "foo" and "bar" are not.

Java Solution 1

We can define a map which tracks the char-char mappings. If a value is already mapped, it can not be mapped again.

public boolean isIsomorphic(String s, String t) {
    if(s.length()!=t.length()){
        return false;
    }
 
    HashMap<Character, Character> map1 = new HashMap<>();
    HashMap<Character, Character> map2 = new HashMap<>();
 
    for(int i=0; i<s.length(); i++){
        char c1 = s.charAt(i);
        char c2 = t.charAt(i);
 
        if(map1.containsKey(c1)){
            if(c2!=map1.get(c1)){
                return false;
            }
        }else{
            if(map2.containsKey(c2)){
                return false;
            }
 
            map1.put(c1, c2);
            map2.put(c2, c1);
        }
    }
 
    return true;
}

Time complexity is O(n) and space complexity is O(n), where n is the length of the input string.

Java Solution 2

We can also simply check if a value is mapped twice by checking the number of unique elements.

public boolean isIsomorphic(String s, String t) {
    if (s.length() != t.length()) {
        return false;
    }
 
    HashMap<Character, Character> map = new HashMap<>();
    for (int i = 0; i < s.length(); i++) {
        char c1 = s.charAt(i);
        char c2 = t.charAt(i);
 
        if (map.containsKey(c1)) {
            if (map.get(c1) != c2) {
                return false;
            }
        } else {
            map.put(c1, c2);
        }
    }
 
    HashSet<Character> set = new HashSet<>(map.values());
    if (set.size() == map.values().size()) {
        return true;
    }
 
    return false;
}
Category >> Algorithms >> Interview >> Java  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>
  • Tochi Eke-okoro

    Using ES6 – Javascript


    const isomorphic = (firstStr, nextStr) => {
    let memo = {}
    const length = firstStr.length

    for (let i = 0; i < length; i++) {
    const firstStrChar = firstStr[i]
    const nextStrChar = nextStr[i]
    const inMemo = memo[firstStrChar]
    if (inMemo) {
    console.log('--- memo logs --- ')
    console.log('memo: ', memo)
    if (inMemo !== nextStrChar) {
    return false
    }
    } else {
    memo[firstStrChar] = nextStrChar
    }
    }
    return true
    }

  • Ujvári Bálint

    wouldnt this return true for strings that are the same length and have the same set of characters in them?
    thats not the same as isomorphic, because the order of the characters is also a factor

  • Ujvári Bálint

    not sure what you mean by “seems its not quote accept”

    but abaab and cddcd are not isomorphic, so Bukary’s solution should not accept them as isomorphic

  • // This has less space complexity

    private static boolean isIsomorphic(String s, String t) throws IllegalAccessException {
    if (s == null || t == null) {
    throw new IllegalAccessException(“null values”);
    }

    if (s.length() != t.length()) {
    return false;
    }

    for (int i = 1; i < s.length(); ++i) {
    boolean sChange = s.charAt(i) == s.charAt(i – 1);
    boolean tChange = t.charAt(i) == t.charAt(i – 1);

    if (sChange != tChange) {
    return false;
    }
    }

    return true;

    }

  • Rakesh Venkatesh

    your solution doesnt work for “egg” and “bab”. Your solution returns true but they are not isomorphic

  • cheng fang

    seems its not quite accept if we use this solution

    isIsomorphic("abaab", "cddcd")

  • Abu Zubayr Muhammad Rasel

    How about following solution in Python?:
    After checking for null and unequal length:

    l1 = list(word1)
    l2 = list(word2)
    pp = {}
    for i, j in enumerate(l1):
    if j not in pp:
    pp[j] = list(l2[i])
    else:
    newls = pp[j]
    newls.append(l2[i])
    pp[j] = newls

    for key, things in pp.items():
    var = len(set(things))
    if var == 1:
    continue
    else:
    print(‘words: ‘{}’and ‘{}’ are not isomorphic’.format(word1, word2))
    break
    if var == 1:
    print(‘words: ‘{}’and ‘{}’ are isomorphic’.format(word1, word2))

  • Abu Zubayr Muhammad Rasel

    How about following solution in Python:

    l1 = list(word1)
    l2 = list(word2)
    pp = {}
    for i, j in enumerate(l1):
    if j not in pp:
    pp[j] = list(l2[i])
    else:
    newls = pp[j]
    newls.append(l2[i])
    pp[j] = newls

    for key, things in pp.items():
    var = len(set(things))
    if var == 1:
    continue
    else:
    print(‘words: ‘{}’and ‘{}’ are not isomorphic’.format(word1, word2))
    break
    if var == 1:
    print(‘words: ‘{}’and ‘{}’ are isomorphic’.format(word1, word2))

  • Aafreen Sheikh

    The containsValue check can be avoided if we use the map as a bidirectional map. So when we find that ‘e’ maps to ‘a’, we first check that map.contains(‘a’) and map.contains(‘e’) both should be false. If so, we do: map.put(‘e’,’a’) and map.put(‘a’,’e’). This way we can look up both ways and implement this code in O(1).

  • Bukary Kandeh

    Yet Another Solution 🙂 See my code in the link or below code:
    https://ide.geeksforgeeks.org/zuwGLQKlWV

    private static boolean isIsomorphic(String s, String t) {
    if(s == null || t == null) return false;
    if(s.length() != t.length()) return false;

    Map sMp = new HashMap();
    for(char ch : s.toCharArray()){
    if(sMp.containsKey(ch)){ sMp.put(ch, sMp.get(ch) + 1); }
    else sMp.put(ch, 1);
    }

    Map tMp = new HashMap();
    for(char ch : t.toCharArray()){
    if(tMp.containsKey(ch)){ tMp.put(ch, tMp.get(ch) + 1); }
    else tMp.put(ch, 1);
    }
    if(sMp.size() != tMp.size()) return false;

    List lstOne = new ArrayList();
    for(Integer entryOne : sMp.values()){ lstOne.add(entryOne.intValue()); }

    List lstTwo = new ArrayList();
    for(Integer entryTwo : tMp.values()){ lstTwo.add(entryTwo.intValue()); }

    Collections.sort(lstOne);
    Collections.sort(lstTwo);
    for (int i=0; i<lstOne.size(); i++){
    if(lstOne.get(i) != lstTwo.get(i)){ return false; }
    }
    return true;
    }

  • LR

    aab and xzz are not isomorphic as a->x and a->z

  • Arezou Moussavi

    Given handling the empty cases and wrong types (from other solutions) this works in python:
    if len(set(str1)) != len(set(str2)):
    print (‘False’)
    else:
    print(‘True’)

  • Partha Pratim Sanyal

    map.containsValue() is a O(n) operation, so the solution presented above is O(n^n)

  • jlogan

    Does any of these solution work for
    “aab”, “xzz”

    a->z
    b->x makes this isomorphic,

    but every one of the solutions i have seen (geeks,leet,sovflow, this one) do not address this. Highly likely i got my isomorphism wrong.

    Please help.

  • dan

    bool checkMap(string s1, string s2)
    {
    Dictionary m = new Dictionary();
    for (int i = 0; i < s1.Length; i++)
    {
    if (m.ContainsKey(s1.Substring(i, 1)) || m.ContainsValue(s2.Substring(i, 1))) continue;
    m.Add(s1.Substring(i, 1), s2.Substring(i, 1));
    }
    foreach(KeyValuePair item in m){
    s2=s2.Replace(item.Value, item.Key);
    }
    if (s1 == s2)
    return true;
    else return false;
    }

  • jitendra

    if len(s)==len(t):
    for in range(len(s)):
    s=s.replace(s[i],t[i])
    if s==t:
    print(‘they are isomorphic’)

  • Ahmed Saad

    Hi,
    The solution above has O(N2) time complexity as map.containsValue(c2) will run in O(N) not O(1_

  • Greg Mueller

    Here’s what I came up with:


    def is_isomorphic(source, target):
    if type(source) != type('') or type(target) != type(''):
    raise ValueError('Source and Target must be of type string.')
    char_map = {}
    for s, t in zip(source, target):
    if t != char_map.setdefault(s, t):
    return False
    return True if len(source) == len(target) else False

  • Udaydeep Thota

    You code doesn’t work for “ab” and “aa”

  • Samir

    Hi,
    Below code runs fine for given input s=”ab”,t=”aa” ; on eclipse but not on leetcode’s compliter.
    Please help me to explore the reason.
    However this code was able to pass 26/30 test case and takes 3ms of execution time.
    thanx in advance


    public boolean isIsomorphic(String s, String t) {
    if(s.equals("") || t.equals("")){
    return true;
    }

    String sArray[] = s.split("");
    String tArray[] = t.split("");
    Map sMap= new HashMap();
    Map tMap= new HashMap();
    Set sSet = new HashSet();
    Set tSet = new HashSet();

    for(int i=1;i<sArray.length;i++){
    sMap.put(i, sArray[i]);
    }
    for(int i=1;i<sArray.length;i++){
    tMap.put(i, tArray[i]);
    }
    for(Integer key1 : sMap.keySet()){
    sSet.add(sMap.get(key1));
    }
    for(Integer key2 : tMap.keySet()){
    tSet.add(tMap.get(key2));
    }
    System.out.println(sSet+" "+tSet);
    if(sSet.size() == tSet.size() ){
    return true;
    }else{
    return false;
    }
    }

  • Samir

    For input String str1=”aba”, str2=”baa”; this code will not work

  • Samir

    Very easy solution


    public boolean isIsomorphic(String s, String t) {
    if(s==null||t==null)
    return false;

    String sArray[] = s.split("");
    String tArray[] = t.split("");
    Set sSet= new HashSet(Arrays.asList(sArray));
    Set tSet= new HashSet(Arrays.asList(tArray));
    System.out.println(sSet.size()+" "+tSet.size());
    if(sSet.size() == tSet.size()){
    return true;
    }
    else{
    return false;
    }

    }

  • Nakeer

    should be (s1 != null && s2 != null && s1.length() == s2.length() ) {
    }
    return false;

  • Nakeer

    Actually if you use && it will be much more faster

    if (s1.length() == s2.length() && s1 != null && s2 != null) {
    }
    return false;

  • Guy Kahlon

    How does this solution is O (n) time? The operation containsValue itself is O(n) time, so, in the worst case this solution can take O(n^2) time.

  • Mahesh V Shet (CP QA-BLR)

    Here is my Solution:

  • Matias SM

    I believe that you only need a (hash)set to check if a mapping already exists. If it does, then the creation of a new one would make the strings not isomorphic.

    You would use the first map to check if the current char (source str) has already a mapping, and the set to check if a new mapping can be created (to the char in the dst str).

  • Roger Camargo

    A python solution:


    def is_isomorphic(first, second):
    if not first or not second:
    return False
    if len(first) != len(second):
    return False
    word_map = {}
    final_word = ""
    for position in range(len(first)):
    word_map.update({first[position]: second[position]})

    for char in first:
    final_word += word_map[char]
    return final_word == second

    def test_isomorphic():
    assert is_isomorphic("egg", "add") == True
    assert is_isomorphic("foo", "bar") == False
    assert is_isomorphic("abca", "zbxz") == True
    assert is_isomorphic("ab", "zbxz") == False
    assert is_isomorphic("", "zbxz") == False
    assert is_isomorphic(None, "zbxz") == False

  • Luis Zafra

    I think this work fine:


    import java.util.HashMap;
    import java.util.Map;

    public class Isomorphic {

    public static void main(String[] args) {
    String a = "add";
    String b = "egg";

    System.out.println(isIsomorphic(a, b));
    }

    private static boolean isIsomorphic(String s, String t) {
    if (s == null || t == null || (s.length() != t.length())) {
    return false;
    }
    if (s.length() == 0 && t.length() == 0) {
    return true;
    }

    Map map = new HashMap();
    for (int i = 0; i < s.length(); i++) {
    Character c1 = s.charAt(i);
    Character c2 = t.charAt(i);
    if (!map.containsKey(c1)) {
    if (!map.containsValue(c2)) {
    map.put(c1, c2);
    } else {
    return false;
    }
    } else if (!map.get(c1).equals(c2)) {
    return false;
    }
    }
    return true;
    }
    }

  • Michael Voong

    Swift:

    func isIsomorphic(s1: String, s2: String) -> Bool {

    if s1.characters.count == 0 {

    return false

    }

    if s1.characters.count != s2.characters.count {

    return false

    }

    let s1Array = s1.characters.map { String($0) }

    let s2Array = s2.characters.map { String($0) }

    var map = [String: String]()

    for (i, s1Value) in s1Array.enumerate() {

    if let existingValue = map[s1Value] where existingValue != s2Array[i] {

    return false

    }

    map[s1Value] = s2Array[i]

    }

    return true

    }

  • Ankit Shah

    import java.util.*;
    public class IsomorphicString {
    public static boolean isomorphic(String s, String t) {
    if(s == null) {
    return false;
    }

    if(t == null) {
    return false;
    }

    if(s.length() != t.length()) {
    return false;
    }

    if(s.length() == 0 && t.length() == 0) return true;
    Map map = new HashMap();
    for(int i = 0; i < s.length(); i++) {
    if(map.containsKey(s.charAt(i))) {
    if(map.get(s.charAt(i)) != t.charAt(i)) {
    return false;
    }
    } else {
    map.put(s.charAt(i), t.charAt(i));
    }
    }
    return true;
    }
    public static void main(String[] args) {
    String s = "egg";
    String t = "ftd";
    System.out.println(isomorphic(s,t));
    }
    }

  • Guest

    This solution is in efficient as you are iterating over entire Map for every single character. Why not have to maps
    map1 for source –> target mapping and
    map2 for target –> source mapping

  • Ryan Shaw

    Python solution. Passed in Leetcode OJ.

    def is_isomorphic(a, b):
    """Returns true if a is isomorphic to b. It does not guarantee b is isomorphic to a."""
    if a is None: return b is None
    if b is None: return a is None
    if len(a) != len(b): return False

    diff_map = {}
    for i in xrange(len(a)):
    c = a[i]
    diff = ord(a[i]) - ord(b[i])
    if c in diff_map:
    if diff != diff_map[c]:
    return False
    else:
    diff_map[c] = diff
    return True

    def is_bi_isomorphic(a, b):
    return is_isomorphic(a, b) and is_isomorphic(b, a)

  • Ryan Shaw

    Your solution produce incorrect result for:

    case: s1 = ”, s2 = ‘a’

    case: s1 = ‘a’, s2 = ‘b’

  • Allali Elkhalili

    I think you are right, i changed the code, and i think this one work

    public static boolean isIsomorphic(String s, String t) {

    if (s == null || t == null)

    return false;

    if (s.length() != t.length())

    return false;

    if (s.length() == 0 && t.length() == 0)

    return true;

    HashMap map = new HashMap();

    for (int i = 0; i < s.length(); i++) {

    char c1 = s.charAt(i);

    char c2 = t.charAt(i);

    map.put(c1, c2);

    }

    for (int i = 0; i < s.length(); i++) {

    char c1 = s.charAt(i);

    char c2 = t.charAt(i);

    List list = getKey(map, c2);

    if (!list.isEmpty() && !list.contains(c1)) {

    return false;

    } else if (map.containsKey(c1)) {

    if (c2 != map.get(c1))

    return false;

    }

    }

    return true;

    }

    // a method for getting key of a target value

    public static List getKey(HashMap map, Character target) {

    List characters = new ArrayList();

    for (Map.Entry entry : map.entrySet()) {

    if (entry.getValue().equals(target)) {

    characters.add(entry.getKey());

    }

    }

    return characters;

    }

  • hive


    public boolean isIsomorphic(String s1, String s2) {
    int[] m = new int[512];
    for (int i = 0; i < s1.length(); i++) {
    System.out.println(i + " " + (s1.charAt(i)+0) + " " +(s2.charAt(i)+256));
    if (m[s1.charAt(i)] != m[s2.charAt(i) + 256]) {
    return false;
    }
    m[s1.charAt(i)] = m[s2.charAt(i) + 256] = i + 1;
    }
    return true;
    }

  • ameykelkar

    How about this solution?

    public class Solution {
    public boolean isIsomorphic(String s, String t) {
    // Return true if both the strings are null
    if(s.equals("") && t.equals("")) {
    return true;
    }

    // Create a HashMap for one to one mapping
    HashMap sToT = new HashMap();
    HashMap tToS = new HashMap();

    // Iterate each character
    for(int i = 0; i < s.length(); i++) {
    Character s1 = (Character) s.charAt(i);
    Character t1 = (Character) t.charAt(i);
    if(sToT.containsKey(s1) && sToT.get(s1) != t1) {
    return false;
    }
    else {
    sToT.put(s1, t1);
    }
    if(tToS.containsKey(t1) && tToS.get(t1) != s1) {
    return false;
    }
    else {
    tToS.put(t1, s1);
    }
    }
    return true;
    }
    }

  • Ashwin

    This also works I guess,

    public static void isIsomorphic(String str1, String str2){

    Set set1 = new HashSet();
    Set set2 = new HashSet();

    char[] charArray1 = str1.toCharArray();
    char[] charArray2 = str2.toCharArray();

    for(char t : charArray1){
    set1.add(String.valueOf(t));
    }

    for(char t : charArray2){
    set2.add(String.valueOf(t));
    }

    System.out.println(“size of set1 ” + set1.size());
    System.out.println(“size of set2 ” + set2.size());

    if(set1.size() == set2.size())
    System.out.println(str1 + ” and ” + str2 + ” are Isomorphic”);
    else
    System.out.println(str1 + ” and ” + str2 + ” are Not Isomorphic”);

    System.out.println();
    }

  • saurabh raj

    import java.util.HashMap;
    public class Isomorphic {

    public boolean Check(String str1 , String str2){
    if(str1 == null || str2 == null){
    return false;
    }
    if( str1.length() != str2.length()){
    return false;
    }
    if( ! (charAtPosition(str1).toString().equals(charAtPosition(str2).toString())) ) {
    return false;
    }

    return true;
    }

    public StringBuilder charAtPosition(String str) {
    HashMap hm = new HashMap();
    StringBuilder charPos = new StringBuilder();
    for(int i =0 ; i < str.length() ; i++) {
    if( hm.containsKey(String.valueOf(str.charAt(i)))) {
    charPos.append(hm.get(String.valueOf(str.charAt(i))));

    } else {
    hm.put(String.valueOf(str.charAt(i)), i);
    charPos.append(i);
    }
    }
    System.out.println(str + " " + charPos);

    return charPos;
    }

    public static void main(String args[])
    {
    System.out.println(System.currentTimeMillis());
    Isomorphic ism = new Isomorphic();

    System.out.println(ism.Check("abba", "noon"));
    System.out.println(System.currentTimeMillis());
    }

    }

  • roman

    if(s.length()!=t.length()) {

    System.out.println(“it`s not isomorhic”);

    }

    for(int i=0;i<s.length();i++){

    char c1=s.charAt(i);

    char c2=t.charAt(i);

    if(s.charAt(i)== s.charAt(i+1)){

    if(t.charAt(i)==t.charAt(i+1)){

    System.out.println("it's isomorphic");}

    }

  • This was so useful and informative about JAVA. The article helped me to learn something new. By Juliaroberts

  • The question is ill-posed owing to a poor definition of isomorphic. The map needs to work both ways, otherwise foo is not isomorphic to bar, but bar is isomorphic to foo (replace b with f, and both a and r with o). In other words the mapping needed to make the changes must itself be a set isomorphism.

  • Asutosh

    This runs faster. (320ms)
    The original solution. – 512ms.

  • Asutosh

    public boolean isIsomorphic(String s, String t) {

    if((s.length() != t.length()) || s == null || t == null)

    return false;

    HashMap map = new HashMap();

    for (int i = 0; i < s.length(); i++) {

    char c = s.charAt(i);

    char d = t.charAt(i);

    if (map.containsKey(c)){

    if (map.get(c) != d)

    return false;

    }

    else {

    if (!map.containsValue(d))

    map.put(c, d);

    else

    return false;

    }

    }

    return true;

    }

  • sundaram tiwari

    How about we keep it simple, match the characters for repetition in both strings:

    private static boolean isIsomorphic(String s, String t){
    if(s == null || t == null) {
    return false;
    }
    if(s.length() != t.length()){
    return false;
    }
    char[] sarr = s.toCharArray();
    char[] tarr = t.toCharArray();

    for(int i=0; i<sarr.length; i++){
    int j=i;
    while (j<sarr.length-1 && sarr[j] == sarr[j+1]){
    if(tarr[j] == tarr[j+1]){
    j = j+1;
    }else{
    return false;
    }
    }
    }
    return true;
    }

  • Gdevice

    Isn’t this one simpler? I don’t understand why do you check the key and not the value?

    public boolean isIsomorphic(String s, String t) {

    if (s == null || t == null)

    return false;

    if (s.length() != t.length())

    return false;

    if (s.length() == 0 && t.length() == 0)

    return true;

    HashMap map = new HashMap();

    for (int i = 0; i < s.length(); i++) {

    char c1 = s.charAt(i);

    char c2 = t.charAt(i);

    Character c = map.get(c1);

    if (c != null && c != c2) {

    return false;

    } else {

    map.put(c1, c2);

    }

    }

    return true;

    }