LeetCode205 算法分析

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)的算法写出来也就图一乐)
思路很直白,我就不多解释了
但是算法真的很不巧妙,甚至可以说烂了
只有在匹配字符串很短的时候勉强可以用一下

优化过后的正解

仔细分析以后,
我觉得题目的重点是突出如何有效对字符串进行映射
再进一步思考我们会发现两个有效途径:

  1. 使用Map容器对两个字符串进行映射
  2. 进两个字符串分别映射到新的字符串上

需要注意一点,第一种方法需要调用两次映射
比如 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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值