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.

Analysis

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

Java Solution

public boolean isIsomorphic(String s, String t) {
    if(s==null||t==null)
        return false;
 
    if(s.length()!=t.length())
        return false;
 
    HashMap<Character, Character> map = new HashMap<Character, Character>();
 
 
    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)// if not consistant with previous ones
                return false;
        }else{
            if(map.containsValue(c2)) //if c2 is already being mapped
                return false;
            map.put(c1, c2);
        }
    }
 
    return true;
}

Time is O(n).

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

    }