{x}
blog image

String Transforms Into Another String

Solution Explanation for String Transforms Into Another String

This problem asks whether we can transform string str1 into string str2 using a specific type of conversion: converting all occurrences of a character in str1 to another lowercase English character.

Approach:

The solution employs a hash table (or dictionary in Python) to track the character mappings during the transformation. The core idea is to check for conflicts: if a character in str1 is already mapped to a different character, the transformation is impossible. A secondary check verifies that if str2 uses all 26 lowercase letters, no transformation is possible because there's no way to map any remaining characters in str1 without conflict.

Algorithm:

  1. Handle Identical Strings: If str1 and str2 are identical, the transformation is trivially possible. Return true.

  2. Check for All Characters in str2: Create a set (or use a frequency count) to check if str2 contains all 26 lowercase English letters. If so, it's impossible to transform str1 to str2 because there would be no character left to map to. Return false.

  3. Character Mapping: Iterate through str1 and str2 simultaneously.

    • For each character c in str1, check if it's already in the mapping (hash table d).
    • If c is not in d, add a mapping from c to the corresponding character in str2.
    • If c is in d, check if its mapped character matches the corresponding character in str2. If not, there's a conflict, and the transformation is impossible. Return false.
  4. Success: If the loop completes without conflicts, the transformation is possible. Return true.

Time Complexity: O(n), where n is the length of the strings. We iterate through the strings once.

Space Complexity: O(1) in the worst case. The hash table (or equivalent data structure) stores at most 26 character mappings (one for each lowercase letter). This is constant space, independent of the input string lengths.

Code Examples (with explanations):

The code examples in Python, Java, C++, Go, and TypeScript all follow the algorithm described above. The key differences lie in syntax and the specific data structures used (dictionaries/maps/arrays).

Python3:

class Solution:
    def canConvert(self, str1: str, str2: str) -> bool:
        if str1 == str2:  #Identical strings: Trivial case
            return True
        if len(set(str2)) == 26: #str2 uses all 26 characters, impossible to map
            return False
        mapping = {}
        for i in range(len(str1)):
            char1, char2 = str1[i], str2[i]
            if char1 not in mapping:
                mapping[char1] = char2
            elif mapping[char1] != char2: #Conflict: Already mapped to a different character
                return False
        return True

Java:

class Solution {
    public boolean canConvert(String str1, String str2) {
        if (str1.equals(str2)) return true;
        Set<Character> set = new HashSet<>();
        for (char c : str2.toCharArray()) set.add(c);
        if (set.size() == 26) return false;
        Map<Character, Character> map = new HashMap<>();
        for (int i = 0; i < str1.length(); i++) {
            char c1 = str1.charAt(i), c2 = str2.charAt(i);
            if (!map.containsKey(c1)) map.put(c1, c2);
            else if (map.get(c1) != c2) return false;
        }
        return true;
    }
}

The other language examples (C++, Go, TypeScript) implement similar logic, adapting the syntax and data structures according to the language specifics. They all achieve the same time and space complexity.