[leetcode 雙周賽 6] 1153 字符串轉化


1153 String Transforms Into Another String 字符串轉化

描述

給出兩個長度相同的字符串,分別是 str1str2。請你幫忙判斷字符串 str1 能不能在 零次多次 轉化后變成字符串 str2。
每一次轉化時,將會一次性將 str1 中出現的 所有 相同字母變成其他 任何 小寫英文字母(見示例)。

只有在字符串 str1 能夠通過上述方式順利轉化為字符串 str2 時才能返回 True,否則返回 False。​​

  • 示例 1:

輸入:str1 = "aabcc", str2 = "ccdee"
輸出:true
解釋:將 'c' 變成 'e',然后把 'b' 變成 'd',接着再把 'a' 變成 'c'。注意,轉化的順序也很重要。

  • 示例 2:

輸入:str1 = "leetcode", str2 = "codeleet"
輸出:false
解釋:我們沒有辦法能夠把 str1 轉化為 str2。

  • 提示:

1 <= str1.length == str2.length <= 10^4
str1 和 str2 中都只會出現 小寫英文字母

思路

轉化的定義: 一次性將字符串中出現的 所有 相同字母變成其他 任何 小寫英文字母
例如:aabcc --> ccbcc(a轉化成c) --> eebee(c轉化成e)

由上圖可以看出:
轉化的真正意義是 多對一映射 如此可以得出以下判斷依據:

  • 判斷依據一: 字符種類
    轉化后的字符種類必定小於或者剛好等於轉化前的字符種類
    注意:這種映射是有限制的, 它只能轉化成小寫字母, 即它只能在26個小寫字母之間轉化,
    所以目標字符串的字符種類不能為26(滿值), 除非兩字符串相等, 否則必定無法轉化

  • 判斷依據二: 映射表
    可以建立映射表, 查看是否為多對一的映射

代碼實現

  • 使用兩個HashMap來構建映射表

使用兩個HashMap來構建映射表

class Solution {
    public boolean canConvert(String str1, String str2) {
        if (null == str1 | null == str2) return false;
        // 兩字符串長度不一必定無法轉化
        if (str1.length() != str2.length()) return false;
        // 兩字符串相等 無需轉化
        if (str1.equals(str2)) return true;
        
        // 求元素種類
        HashSet<Character> set = new HashSet<>();
        for (char c : str1.toCharArray()) set.add(c);
        int size1 = set.size();
        set.clear();
        for (char c : str2.toCharArray()) set.add(c);
        int size2 = set.size();
        // 轉換字符串str2元素種類滿26 必定無法轉化
        // 轉化后字符串元素種類比轉化前還多
        if (size2 == 26 | size1 < size2) return false;
        
        // 建立映射表
        // str1ToStr2 存放被轉化字符串的字符及其轉化后字符所對應的標識label     字符 -> label 多對一
        HashMap<Character, Integer> str1ToStr2 = new HashMap<>();
        // str2Table 存放轉化后字符所對應的標識label        字符 -> label 一對一
        HashMap<Character, Integer> str2Table = new HashMap<>();
        // label 轉化后字符所對應的標識label
        int label = 0;
        // 遍歷字符
        char c1, c2;
        for (int i = 0; i < str1.length(); i++) {
            c1 = str1.charAt(i);
            c2 = str2.charAt(i);
            
            // c1 --> c2
            // c2沒有被標識
            if (!str2Table.containsKey(c2)) {
                // c1已經有轉化對應字符了 c1!->c2 多對多
                if (str1ToStr2.containsKey(c1)) return false;
                // c1 -> label
                str1ToStr2.put(c1, label);
                // c2 -> label
                str2Table.put(c2, label);
                label++;
            }
            // c2已經被標識 c1沒有被標識(還沒有確定轉化字符)
            if (!str1ToStr2.containsKey(c1)) {
                // c1 -> label -> c2
                str1ToStr2.put(c1, str2Table.get(c2));
            }
            // c1,c2都已經被標識 查看兩者標識是否相同
            // c1 -> label ?-> c2
            if (str1ToStr2.get(c1) != str2Table.get(c2)) {
                return false;
            }
        }
        return true;
    }
}
  • 使用數組來構建映射表

使用數組來構建映射表

class Solution {
    public boolean canConvert(String str1, String str2) {
        if (null == str1 | null == str2) return false;
        // 兩字符串長度不一必定無法轉化
        if (str1.length() != str2.length()) return false;
        // 兩字符串相等 無需轉化
        if (str1.equals(str2)) return true;
        
        // 求元素種類
        int n = str1.length(), size1 = 0, size2 = 0, p = 0, q = 0;
        boolean[] v1 = new boolean[30];
        boolean[] v2 = new boolean[30];
        for (int i = 0; i < n; i++) {
            p = str1.charAt(i) - 'a';
            q = str2.charAt(i) - 'a';
            if (!v1[p]) {
                size1++;
                v1[p]=true;
            }
            if (!v2[q]) {
                size2++;
                v2[q]=true;
            }
        }
        // 轉換字符串str2元素種類滿26 必定無法轉化
        // 轉化后字符串元素種類比轉化前還多
        if (size2 == 26 | size1 < size2) return false;
        
        // 建立映射表
        // s1ToS2 映射表 下標表示原字符-'a' 值表示目標字符
        char[] s1ToS2 = new char[30];
        char c = '#';
        // 映射表初始化為全'#'
        for (int i = 0; i < 26; i++) s1ToS2[i] = '#';
        for (int i = 0; i < n; i++) {
            p = str1.charAt(i) - 'a';
            c = str2.charAt(i);
            
            // 該字符p還沒有映射
            // 或者
            // 該字符p映射已經映射 且映射單一
            if (s1ToS2[p] == '#' | s1ToS2[p] == c) s1ToS2[p]=c;
            else return false;
        }
        
        return true;
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM