全栈开发知识库

40.同构字符串

题目

给定两个字符串 s 和 t ,判断它们是否是同构的。

如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。

每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。

示例 1:

  • 输入:s = "egg", t = "add"
  • 输出:true

示例 2:

  • 输入:s = "foo", t = "bar"
  • 输出:false

示例 3:

  • 输入:s = "paper", t = "title"
  • 输出:true

提示:

  • 1 <= s.length <= 5 * 104
  • t.length == s.length
  • s 和 t 由任意有效的 ASCII 字符组成

思路

  • “每个出现的字符都应当映射到另一个字符”。代表字符集合 s , t 之间是「满射」。
  • “相同字符只能映射到同一个字符上,不同字符不能映射到同一个字符上”。代表字符集合 s , t 之间是「单射」。
  • 因此, s 和 t 之间是「双射」,满足一一对应。考虑遍历字符串,使用哈希表 s2t , t2s 分别记录 s→t , t→s 的映射,当发现任意「一对多」的关系时返回 false 即可。
class Solution {
    fun isIsomorphic(s: String, t: String): Boolean {
        if (s.length != t.length) {
            return false
        }

        val s2tHash = HashMap<Char, Char>()
        val t2sHash = HashMap<Char, Char>()

        for (i in s.indices) {
            val a = s[i]
            val b = t[i]

            if (s2tHash.contains(a)) {
                if (s2tHash[a] != b) {
                    return false
                }
            } else {
                s2tHash[a] = b
            }

            if (t2sHash.contains(b)) {
                if (t2sHash[b] != a) {
                    return false
                }
            } else {
                t2sHash[b] = a
            }

        }
        return true
    }
}


class Solution {
    public boolean isIsomorphic(String s, String t) {
        Map<Character, Character> s2t = new HashMap<>(), t2s = new HashMap<>();
        for (int i = 0; i < s.length(); i++) {
            char a = s.charAt(i), b = t.charAt(i);
            // 对于已有映射 a -> s2t[a],若和当前字符映射 a -> b 不匹配,
            // 说明有一对多的映射关系,则返回 false ;
            // 对于映射 b -> a 也同理
            if (s2t.containsKey(a) && s2t.get(a) != b || 
                t2s.containsKey(b) && t2s.get(b) != a) {
                return false;
            }
            s2t.put(a, b);
            t2s.put(b, a);
        }
        return true;
    }
}
class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
        s2t = {}
        t2s = {}

        for i in range(len(s)):
            a = s[i]
            b = t[i]

            if (a in s2t and s2t.get(a) != b) or (b in t2s and t2s.get(b) != a):
                return False
            s2t[a] = b
            t2s[b] = a

        return True

复杂度分析:

  • 时间复杂度 O(N) : 其中 N 为字符串 s , t 的长度。遍历字符串 s , t 使用线性时间,hashmap 查询操作使用 O(1) 时间。
  • 空间复杂度 O(1) : 题目说明 s 和 t 由任意有效的 ASCII 字符组成。由于 ASCII 字符共 128 个,因此 hashmap s2t , t2s 使用 O(128)=O(1) 空间。


  • 邮箱 :charon.chui@gmail.com
  • Good Luck!