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;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章