Isomorphic Strings

Updated on 04 June, 2025
Isomorphic Strings header image

Problem Statement

Determining if two given strings, s and t, are isomorphic involves checking if each character in s can be consistently replaced to transform s into t. Isomorphic strings adhere to a specific mapping rule where each character from s maps to exactly one character in t, maintaining their positions and order in the transformed string. Any character in s must map to one unique character in t, and no character should map to multiple characters. However, a character might map to itself.

Examples

Example 1

Input:

s = "egg", t = "add"

Output:

true

Explanation:

The strings `s` and `t` can be made identical by:

* Mapping `'e'` to `'a'`.
* Mapping `'g'` to `'d'`.

Example 2

Input:

s = "foo", t = "bar"

Output:

false

Explanation:

The strings `s` and `t` can not be made identical as `'o'` needs to be mapped to both `'a'` and `'r'`.

Example 3

Input:

s = "paper", t = "title"

Output:

true

Constraints

  • 1 <= s.length <= 5 * 104
  • t.length == s.length
  • s and t consist of any valid ascii character.

Approach and Intuition

Understanding Isomorphism in Strings:

  • Two strings are isomorphic if we can replace individual characters in one string to exactly match the other while preserving the sequential order.
  • An essential nuance of isomorphism is the consistent mapping of characters, where once a character in s is ascribed a corresponding character in t, the same mapping must apply throughout the string.

Steps to Determine if Strings are Isomorphic:

  1. Create Mapping: For every character in s, map it to the corresponding character in t.
    • Use a dictionary or hash map to store this relationship.
  2. Maintain Reverse Mapping: Check for cases where two different characters in s are mistakenly mapped to the same character in t.
    • Another dictionary can store the reverse mapping (from t to s) for cross-validation.
  3. Iterate and Validate: Traverse through the string s. For every new character encountered in s:
    • If the character has a previously established mapping in s to t, check for consistency in this mapping.
    • If a character in t is already mapped from a different character in s, the strings are not isomorphic as this breaks the unique mapping rule.
  4. Consistency Check: Finish the traversal and if all characters have adhered to the mapping rules without any contradiction, the strings are isomorphic.

Examples and Interpretations:

  • Example 1 ("egg" to "add"): Each 'e' in "egg" can be mapped to 'a' and 'g' to 'd'. Every 'g' consistently maps to 'd', thus they are isomorphic.
  • Example 2 ("foo" to "bar"): The character 'o' would need to map to both 'a' and 'r' for the transformation, which violates the isomorphism rule since a character should map to exactly one other character.
  • Example 3 ("paper" to "title"): Here, the respective characters map uniquely across the strings ('p' to 't', 'a' to 'i', 'e' to 'l'), demonstrating that 'paper' and 'title' are isomorphic.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    string convertString(string input) {
        unordered_map<char, int> charPositions;
        string output;

        for (int idx = 0; idx < input.length(); ++idx) {
            char currentChar = input[idx];

            if (charPositions.find(currentChar) == charPositions.end()) {
                charPositions[currentChar] = idx;
            }

            output.append(to_string(charPositions[currentChar]));
            output.append(" ");
        }
        return output;
    }

    bool areIsomorphic(string s1, string s2) {
        return convertString(s1) == convertString(s2);
    }
};

This C++ solution checks whether two strings, s1 and s2, are isomorphic. Two strings are considered isomorphic if the characters in s1 can be replaced to get s2 while maintaining the character order and frequency.

The given code includes a Solution class with two functions:

  1. convertString(string input): This function creates a unique pattern for a input string. It uses an unordered map (charPositions) to track the first occurrence index of each character. As it iterates through the string, if a character has not been seen before, its index is saved in the map. The output string is generated by appending the first occurrence indexes of the characters with spaces in between.

  2. areIsomorphic(string s1, string s2): This function compares the unique patterns of s1 and s2 obtained from convertString. If these patterns match, it returns true, indicating the strings are isomorphic; otherwise, it returns false.

In essence, if the positional template of the first appearances of characters in both strings matches, the strings are considered isomorphic. This approach efficiently checks isomorphism without directly modifying any characters, utilizing patterns and mappings.

java
class Solution {
    private String mapString(String inputStream) {
        Map<Character, Integer> charToIndex = new HashMap<>();
        StringBuilder encoded = new StringBuilder();

        for (int idx = 0; idx < inputStream.length(); idx++) {
            char currentChar = inputStream.charAt(idx);

            if (!charToIndex.containsKey(currentChar)) {
                charToIndex.put(currentChar, idx);
            }

            encoded.append(Integer.toString(charToIndex.get(currentChar)));
            encoded.append(" ");
        }
        return encoded.toString();
    }

    public boolean checkIsomorphic(String str1, String str2) {
        return mapString(str1).equals(mapString(str2));
    }
}

In the Java implementation provided, the program checks if two strings are isomorphic. Two strings are considered isomorphic if the characters in the first string can be replaced to get the second string. The solution follows these steps:

  • Define a mapString function to encode the input string based on the first occurrence index of each character.

    • Initialize a hash map charToIndex to store each character's first index.
    • Use a StringBuilder named encoded to build the resulting encoded string.
    • Iterate through each character in the input string. If the character is not already in the map, add it with its index. Append the index of the character (from the map) to encoded, followed by a space.
    • Return the fully constructed encoded string as the output of the function.
  • The checkIsomorphic method compares the encoded forms of two input strings (str1 and str2):

    • It calls the mapString function for both strings and checks if the outputs are the same.
    • Return true if they match, indicating the strings are isomorphic; otherwise, return false.

The encoding via first occurrence helps to standardize the representation of each character's positional role in the string, allowing a straightforward comparison of structure independent of actual character values. This efficient mapping via a hashmap ensures that each character's first occurrence is uniquely marked, simplifying the check for isomorphic strings.

python
class Solution:

    def convertStr(self, input_str: str) -> str:
        char_to_index = {}
        transformed_str = []

        for position, char in enumerate(input_str):
            if char not in char_to_index:
                char_to_index[char] = position
            transformed_str.append(str(char_to_index[char]))

        return " ".join(transformed_str)

    def stringsIsomorphic(self, str1: str, str2: str) -> bool:
        return self.convertStr(str1) == self.convertStr(str2)

The provided Python code defines a method to determine if two given strings are isomorphic. Isomorphic strings contain characters that can be mapped to each other through a consistent pattern across both strings.

  • The convertStr function takes an input string and creates a transformed string based on the index of the first occurrence of each character. It utilizes a dictionary to store each character's first occurrence index and a list to build the transformed representation of the input string.

  • The transformed string is then returned with its values joined by spaces.

  • The stringsIsomorphic function compares the transformed representations of the two input strings. If the transformed versions are equal, it implies the original strings are isomorphic and returns True, otherwise False.

To utilize this solution:

  1. Create an instance of the Solution class.
  2. Use the stringsIsomorphic method with two strings as arguments to check if they are isomorphic.

This approach efficiently determines the isomorphism by leveraging the ordered mapping of characters to their initial appearance indices, comparing these mappings to infer the required relationship between strings.

Comments

No comments yet.