1. 程式人生 > >LeetCode演算法題-Isomorphic Strings(Java實現)

LeetCode演算法題-Isomorphic Strings(Java實現)

這是悅樂書的第191次更新,第194篇原創

01 看題和準備

今天介紹的是LeetCode演算法題中Easy級別的第50題(順位題號是205)。給定兩個字串s和t,確定它們是否是同構的。如果s中的字元可以替換為t,則兩個字串是同構的。

所有出現的字元必須替換為另一個字元,同時保留字元的順序。 沒有兩個字元可以對映到相同的字元,但字元可以對映到自身。例如:

輸入:s =“egg”,t =“add”
輸出:true

輸入:s =“foo”,t =“bar”
輸出:false

輸入:s =“paper”,t =“title”
輸出:true

注意:可以假設s和t都具有相同的長度。

本次解題使用的開發工具是eclipse,jdk使用的版本是1.8,環境是win7 64位系統,使用Java語言編寫和測試。

02 第一種解法

因為題目已經假設兩個字串的長度是相等的,所以不用考慮特殊情況。

使用兩個HashMap,分別儲存字串s和字串t的每一位字元,再使用兩個新的字串str和str2,分別儲存其對應字元的結構,如果字元已經存在,則取出之前存的下標新增到str或str2中,如果是新出現,就把當前的下標新增到str或str2中。最後得到的str和str2就是s、t所表示的結構,如果str和str2相等,則返回true,否則返回false。

public boolean isIsomorphic(String s, String t) {
    Map<Character, Integer> map = new HashMap<>();
    String str = "";
    for (int i=0; i<s.length(); i++) {
        if (map.containsKey(s.charAt(i))) {
            str = str + map.get(s.charAt(i));
        } else {
            map.put(s.charAt(i), i);
            str += i;
        }
    }
    Map<Character, Integer> map2 = new HashMap<>();
    String str2 = "";
    for (int j=0; j<t.length(); j++) {
        if (map2.containsKey(t.charAt(j))) {
            str2 = str2 + map2.get(t.charAt(j));
        } else {
            map2.put(t.charAt(j), j);
            str2 += j;
        }
    }
    return str.equals(str2);
}

時間複雜度:因為for迴圈中使用了HashMap的containsKey方法,而此方法最好的情況就是要判斷的key正好是第一位,則containsKey方法的時間複雜度是O(1),最壞的情況是要判斷的key在最後一位,則containsKey方法的時間複雜度是O(n)。因此,此解法的時間複雜度最好情況是O(n),最壞情況是O(n^2)。

空間複雜度:O(n)

03 第二種解法

依舊使用兩個HashMap,同樣是將兩個字串的各個字元放入map中,不過由第一種解法的分開放變成同時放,如果在進行put的時候,有兩種情況:當前字元在map中不存在的時候,返回null;當前字元在map中存在的時候,返回此字元作為key所關聯的之前的value。如果兩邊的字元進行put操作而不相等,即說明此字元在兩個map中的其中一個已經出現過一次,但是另外一個沒出現過,也就表示兩字串的結構是不同的。

public boolean isIsomorphic2(String s, String t) {
    Map<Character, Integer> map = new HashMap<>();
    Map<Character, Integer> map2 = new HashMap<>();
    for (Integer i=0; i<s.length(); i++) {
        if (map.put(s.charAt(i), i) != map2.put(t.charAt(i), i)) {
            return false;
        }
    }
    return true;
}


04 第三種解法

只使用一個HashMap。思路與上面兩種解法類似,不過是將字串s的各個字元當成了map的key,將字串t的各個字元當成map的value。只要map中存在當前的字元key,那麼其所對應的value應該和另外一個字串的當前字元相等,否則就是結構不同。

public boolean isIsomorphic3(String s, String t) {
    HashMap<Character, Character> map = new HashMap<>();
    int size = s.length();
    for (int i = 0; i < size; i++) {
        if (map.containsKey(s.charAt(i))) {
            if (t.charAt(i) != map.get(s.charAt(i))) {
                return false;
            }
        } else {
            if (map.containsValue(t.charAt(i))) {
                return false;
            }
            map.put(s.charAt(i), t.charAt(i));
        }
    }
    return true;
}


05 第四種解法

對於上面的解法使用HashMap來存字元,我們可以只用陣列來替代,因為組成字串的字元型別有限,ASCII碼只有256個字元,所以我們預先定義好兩個大小為256的整型陣列,建立後兩陣列中的元素初始值都是0。此時,我們使用for迴圈對字串s進行遍歷,當前字元所表示的十進位制值當做是陣列的索引,如果該索引分別對應的值不相等,則說明兩字串不是同結構,否則,就將迴圈內的指標i作為其索引對應的值。其中i是從0開始的,但是陣列初始化後其內所有元素都是預設值0,所以需要加1來區別預設值0。

public boolean isIsomorphic4(String s, String t) {
    int[] m1 = new int[256];
    int[] m2 = new int[256];
    for (int i = 0; i < s.length(); i++) {
        if (m1[s.charAt(i)] != m2[t.charAt(i)]) return false;
        m1[s.charAt(i)] = i + 1;
        m2[t.charAt(i)] = i + 1;
    }
    return true;
}

此解法時間複雜度是O(n),空間複雜度是O(1)。

06 小結

演算法專題目前已連續日更超過一個月,演算法題文章50+篇,公眾號對話方塊回覆【資料結構與演算法】、【演算法】、【資料結構】中的任一關鍵詞,獲取系列文章合集。

以上就是全部內容,如果大家有什麼好的解法思路、建議或者其他問題,可以下方留言交流,點贊、留言、轉發就是對我最大的回報和支援!