LeetCode 1153 - String Transforms Into Another String


http://leetcode.liangjiateng.cn/leetcode/string-transforms-into-another-string/
Given two strings str1 and str2 of the same length, determine whether you can transform str1 into str2 by doing zero or more conversions.
In one conversion you can convert all occurrences of one character in str1 to any other lowercase English character.
Return true if and only if you can transform str1 into str2.

Example 1:
Input: str1 = "aabcc", str2 = "ccdee"
Output: true
Explanation: Convert 'c' to 'e' then 'b' to 'd' then 'a' to 'c'. Note that the order of conversions matter.
Example 2:
Input: str1 = "leetcode", str2 = "codeleet"
Output: false
Explanation: There is no way to transform str1 to str2.

Note:
  1. 1 <= str1.length == str2.length <= 10^4
  2. Both str1 and str2 contain only lowercase English letters


给出两个长度相同的字符串,分别是 str1 和 str2。请你帮忙判断字符串 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. 1 <= str1.length == str2.length <= 10^4
  2. 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;
    }
}

遍歷一遍str1,就知道str1的每個字符應該映射到誰了
但是1個字符不能映射到2個字符 同時 str1裏的字符個數應該少於str2裏的字符個數
此外,如果str2有26個字符時,除非兩個字符串相等,否則不可能轉化成功,因爲str1此時也得有26個字符,但是不管動了哪個字符,映射完之後就只有25個字符了,這時候無法再映射回26個字符
    def canConvert(self, str1: str, str2: str) -> bool:
        have = set()
        change = {}
        n = len(str1)
        for i in range(n):
            have.add(str2[i])
            if str1[i] not in change:
                change[str1[i]] = str2[i]
            if change[str1[i]] != str2[i]:
                return False
        return len(change)>=len(have) and (len(have)<26 or str1==str2)


Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts