LeetCode 269 - Alien Dictionary


https://zhuhan0.blogspot.com/2017/06/leetcode-269-alien-dictionary.html
There is a new alien language which uses the latin alphabet. However, the order among letters are unknown to you. You receive a list of non-empty words from the dictionary, where words are sorted lexicographically by the rules of this new language. Derive the order of letters in this language.
Example 1:
Given the following words in dictionary,
[
  "wrt",
  "wrf",
  "er",
  "ett",
  "rftt"
]
The correct order is: "wertf".
Example 2:
Given the following words in dictionary,
[
  "z",
  "x"
]
The correct order is: "zx".
Example 3:
Given the following words in dictionary,
[
  "z",
  "x",
  "z"
]
The order is invalid, so return "".
Note:
  1. You may assume all letters are in lowercase.
  2. You may assume that if a is a prefix of b, then a must appear before b in the given dictionary.
  3. If the order is invalid, return an empty string.
  4. There may be multiple valid order of letters, return any one of them is fine.
Topological sort:
  1. Build graph: 
    1. a map of character -> set of character.
    2. Also get in-degrees for each character. In-degrees will be a map of character -> integer.
  2. Topological sort:
    1. Loop through in-degrees. Offer the characters with in-degree of 0 to queue.
    2. While queue is not empty:
      1. Poll from queue. Append to character to result string.
      2. Decrease the in-degree of polled character's children by 1.
      3. If any child's in-degree decreases to 0, offer it to queue.
    3. At last, if result string's length is less than the number of vertices, that means there is a cycle in my graph. The order is invalid.
    Say the number of characters in the dictionary (including duplicates) is n. Building the graph takes O(n). Topological sort takes O(V + E). V <= n. E also can't be larger than n. So the overall time complexity is O(n).

        public String alienOrder(String[] words) {
            Map<Character, Set<Character>> graph = new HashMap<>();
            int[] inDegree = new int[26];
            buildGraph(words, graph, inDegree);
            
            String order = topologicalSort(graph, inDegree);
            return order.length() == graph.size() ? order : "";
        }
        
        private void buildGraph(String[] words, Map<Character, Set<Character>> graph, int[] inDegree) {
            for (String word : words) {
                for (char c : word.toCharArray()) {
                    graph.put(c, new HashSet<>());
                }
            }
            
            for (int i = 1; i < words.length; i++) {
                String first = words[i - 1];
                String second = words[i];
                int length = Math.min(first.length(), second.length());
                
                for (int j = 0; j < length; j++) {
                    char parent = first.charAt(j);
                    char child = second.charAt(j);
                    if (parent != child) {
                        if (!graph.get(parent).contains(child)) {
                            graph.get(parent).add(child);
                            inDegree[child - 'a']++;
                        }
                        break;
                    }
                }
            }
        }
        
        private String topologicalSort(Map<Character, Set<Character>> graph, int[] inDegree) {
            Queue<Character> queue = new LinkedList<>();
            for (char c : graph.keySet()) {
                if (inDegree[c - 'a'] == 0) {
                    queue.offer(c);
                }
            }
            
            StringBuilder sb = new StringBuilder();
            while (!queue.isEmpty()) {
                char c = queue.poll();
                sb.append(c);
                for (char neighbor : graph.get(c)) {
                    inDegree[neighbor - 'a']--;
                    if (inDegree[neighbor - 'a'] == 0) {
                        queue.offer(neighbor);
                    }
                }
            }
            return sb.toString();
        }
    

    X. DFS
    https://github.com/awangdev/LintCode/blob/master/Java/Alien%20Dictionary.java
    - 本质: 上下两行string, 相对应的相同的index上, 如果字母不同, 就说明排在第一行的字母在字母表里更领先
    - 把 string array 变成topological sort的 graph: `map<char, list<char>>`
    - 也可以`List[26] edges` (Course Schedule problem)
    - Build edges: find char diff between two row, and store the order indication into graph
    - 注意: indegree 永远是反向的 (跟 node to neighbors 相反的方式建立)
    
    #### BFS
    - topological sort 本身很好写, 但是要在题目中先了解到字母排序的本质
    - 其实上面这个排序的本质很好想, 但是把它具体化成构建graph的代码, 会稍微有点难想到
    - 算indegree, 然后用 BFS 来找到那些 inDegree == 0的 node
    - 最先inDegree == 0的node, 就排在字母表前面.
    - 下面的解法, 用了Graph: map<Character, List<Character>>, 而不是 List[26], 其实更加试用超过26个字母的dictionary.
    - 如果 `inDegree.size() != result.length()`, there is nodes that did not make it into result. 
    - ex: cycle nodes from input, where inDegree of a one node would never reduce to 0, and will not be added to result
    - In this case, it will be treated as invalid input, and return ""
    
    #### DFS
    - 跟BFS建立 grpah 的过程一模一样
    - DFS的不同在于: 用visited map 来标记走过的地方
    - 走到leaf的时候, add to result: 但因为走到了底才add, 最终的顺序应该颠倒 (或者, sb.insert(0, x) 直接用颠倒的顺序add)
    
    DFS, mark visited. When dfs down to an leaf element,
    it'll be the last element of the final output. (reverse order)
    */
        Map<Character, List<Character>> graph = new HashMap<>();
        Map<Character, Integer> visited = new HashMap<>();
        StringBuffer sb = new StringBuffer();
        
        public String alienOrder(String[] words) {
            if (words == null || words.length == 0) {
                return "";
            }
    
            // Build graph, and visited map.
            buildGraph(words);
            
            // Topological sort with dfs
            for (char c : graph.keySet()) {
                if (!dfs(c)) {
                    return "";
                }
            }
            
            return sb.toString();
        }
        
        private boolean dfs(Character c) {
            if (visited.get(c) == 1) return true;
            if (visited.get(c) == -1) return false;
                
            visited.put(c, -1);
            for (char edgeNode : graph.get(c)) {
                if (!dfs(edgeNode)) {
                    return false;
                }
            }
            visited.put(c, 1);
            sb.insert(0, c); // leaf element, add to buffer
            return true;
        }
        
        private void buildGraph (String[] words) {
            // Create nodes
            for (String word: words) {
                for (char c : word.toCharArray()) {
                    if (!graph.containsKey(c)) {
                        graph.put(c, new ArrayList<>());
                        visited.put(c, 0);
                    }
                }
            }
            
            // Build edges
            for (int i = 0; i < words.length - 1; i++) {
                int index = 0;
                while (index < words[i].length() && index < words[i + 1].length()) {
                    char c1 = words[i].charAt(index);
                    char c2 = words[i + 1].charAt(index);
                    if (c1 != c2) {
                        graph.get(c1).add(c2);
                        break;
                    }
                    index++;
                }
            }
        }

    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