LeetCode205
题目简述
判断两个字符串是否同构
难度:简单
描述:
给定两个字符串 s 和 t,判断它们是否是同构的。
如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的。
所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。两个字符不能映射到同一个字符上,但字符可以映射自己本身。
示例 1:
输入: s = "egg", t = "add"
输出: true
示例 2:
输入: s = "foo", t = "bar"
输出: false
示例 3:
输入: s = "paper", t = "title"
输出: true
说明:
你可以假设 s 和 t 具有相同的长度。
题解
不具有参考价值的暴力解法
今天是计划好挑一道简单难度的题练练手的,也不打算写题解了
看到这题时原本还以为是KMP算法的某种变形
结果点进去一看,
吼,有点意思
再一看通过率,
吼,40%出头,在简单题里是比较低了
这时我灵机一动,用C++潇潇洒洒地写了几行代码:
class Solution {
public:
bool isIsomorphic(string s, string t) {
int len = s.size();
for(int i = 0; i < len - 1; i++)
for(int j = i + 1; j < len; j++) {
if(s[i] == s[j] && t[i] != t[j]) return false;
if(t[i] == t[j] && s[i] != s[j]) return false;
}
return true;
}
};
试着提交了一下
不出我所料,超时
(咳咳这种O(n^2)的算法写出来也就图一乐)
思路很直白,我就不多解释了
但是算法真的很不巧妙,甚至可以说烂了
只有在匹配字符串很短的时候勉强可以用一下
优化过后的正解
仔细分析以后,
我觉得题目的重点是突出如何有效对字符串进行映射
再进一步思考我们会发现两个有效途径:
- 使用Map容器对两个字符串进行映射
- 进两个字符串分别映射到新的字符串上
需要注意一点,第一种方法需要调用两次映射
比如 ab->cc 是合法的映射
但是 cc->ab 显然不合法
而第二种方式,例如:
将 add 映射为122
将 egg 也映射为 122
由此进行比较
但我们可以发现,如果字符串很长,假设:
s.szie() = t.size() = 10^8
如果第十位就出现了明显的偏差
上述算法均需要把之后的位置全部比较一遍才能得出结论
这无疑是没有意义的
所以沿用第二种思路,
只要用两个 map 分别记录两个字符串每个字母的映射,将所有字母初始都映射到 0,记录过程中,如果发现了当前映射不一致,就可以立即返回 false 了,这样大大减少了无用的映射过程
代码实现如下(Java):
class Solution {
public boolean isIsomorphic(String s, String t) {
int len = s.length();
int[] mapS = new int[128];
int[] mapT = new int[128];
for(int i = 0; i < len; i++) {
char c1 = s.charAt(i);
char c2 = t.charAt(i);
if(mapS[c1] != mapT[c2]) return false;
else {
if(mapS[c1] == 0) {
mapS[c1] = i + 1;
mapT[c2] = i + 1;
}
}
}
return true;
}
}