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;
}

46 thoughts on “LeetCode – Isomorphic Strings (Java)”

  1. 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
    }

  2. 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

  3. 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

  4. // 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;

    }

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

  6. 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))

  7. 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))

  8. 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).

  9. 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;
    }

  10. 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’)

  11. 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.

  12. 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;
    }

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

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

  15. 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

  16. 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;
    }
    }

  17. 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;
    }

    }

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

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

  19. 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.

  20. 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).

  21. 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

  22. 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;
    }
    }

  23. 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

    }

  24. 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));
    }
    }

  25. 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

  26. 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)

  27. 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;

    }


  28. 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;
    }

  29. 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;
    }
    }

  30. 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();
    }

  31. 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());
    }

    }

  32. 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");}

    }

  33. 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.

  34. 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;

    }

  35. 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;
    }

  36. 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;

    }

Leave a Comment