Leetcode #205. Isomorphic Strings刷题手记

103 阅读3分钟

205. Isomorphic StringsLeetcode面试榜单Top150哈希表类第2题,给定两个字符串,问是否可以通过字符替换把其中一个字符串变成另一个字符串。难度为Easy,简单但不熟悉,怎么办?

题目很清晰易懂,同构(isomorphic)一词不熟,但是它的定义解释也很明了。了解过题意,对感觉这么简易的题,难免产生快一点得到解题方案的心理预期,感觉到思考并不能如意地,流畅的跑起来,甚至有点僵住了,焦虑伴随着自怨自艾的倾向开始有涌动的倾向,主要困惑就在怎么用程序设计的方法来描述1.一个字符串的结构信息,2.保持结构信息,字符替换又是怎么表达。

在几分钟内没打开思路,就想着看看暴力解法是什么?(循环)递归,分治和动态规划三大算法范式能不能套用其中一个?也不能确定。有个暂时降低难度的想法,就是如果不要求保留字符顺序的话,似乎更容易一点(缓解条件,缓解思考压力)那样就和哈希表前一题383. Ransom Note相同的含义,只需要统计两个字符串的字符及其频率应该就够了。 不要求保留结构的话,思路有了,接下来就想办法在这基础之上,看看怎么处理结构相关的信息。有一个想法是同样统计两个字符在各自字符串中出现的位置列表,然后再逐步比较两个字符串各个位置字符对应出现的位置列表相同与否决定结果。

到此暂停,不去写代码实现了,通过搜索查找看看其他可能得方案思路(用树和图的遍历方式来类比,直接冲进去写代码实现是深度优先,这里改用广度优先方式来体验另一种刷题体验)。看看其他的方法方式,是怎么处理结构信息和判断替换字符以获得是否是同构字符串的判定。

在leetcode的一个讨论贴中汇总了各种各样的解法(python语言版):

适合在面试场景中运用的选择有1.逐个字符位置遍历两个字符串,构建并利用字符映射表(哈希表)判断,和2.字符串中的字符映射成该字符首次出现的位置索引,得到字符串的结构序列,使用结构序列比对可得知原字符串是否同构。

构建字符映射表的方法,时间复杂度O(n),空间复杂度O(1)--字符串所用字符个数恒定有限。

class Solution {
    public boolean isIsomorphic(String s, String t) {
        
        int[] mappingDictStoT = new int[256];
        Arrays.fill(mappingDictStoT, -1);
        
        int[] mappingDictTtoS = new int[256];
        Arrays.fill(mappingDictTtoS, -1);
        
        for (int i = 0; i < s.length(); ++i) {
            char c1 = s.charAt(i);
            char c2 = t.charAt(i);
            
            // Case 1: No mapping exists in either of the dictionaries
            if (mappingDictStoT[c1] == -1 && mappingDictTtoS[c2] == -1) {
                mappingDictStoT[c1] = c2;
                mappingDictTtoS[c2] = c1;
            }
            
            // Case 2: Ether mapping doesn't exist in one of the dictionaries or Mapping exists and
            // it doesn't match in either of the dictionaries or both 
            else if (!(mappingDictStoT[c1] == c2 && mappingDictTtoS[c2] == c1)) {
                return false;
            }
        }
        
        return true;
    }
}

构建字符串的结构序列方法,时间和空间复杂度都是O(n)

class Solution {
    private String transformString(String s) {
        Map<Character, Integer> indexMapping = new HashMap<>();
        StringBuilder builder = new StringBuilder();
        
        for (int i = 0; i < s.length(); ++i) {
            char c1 = s.charAt(i);
            
            if (!indexMapping.containsKey(c1)) {
                indexMapping.put(c1, i);
            }
            
            builder.append(Integer.toString(indexMapping.get(c1)));
            builder.append(" ");
        }
        return builder.toString();
    }
    
    public boolean isIsomorphic(String s, String t) {
        return transformString(s).equals(transformString(t));
    }
}