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;
}
}