Jerry's Blog

Recording what I learned everyday

View on GitHub


2 August 2020

LeetCode(269) -- Alien Dictionary

by Jerry Zhang

Problem

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:

Input:
[
  "wrt",
  "wrf",
  "er",
  "ett",
  "rftt"
]

Output: "wertf"

Solution

BFS:

class Solution {
    public String alienOrder(String[] words) {
        Map<Character, List<Character>> adjList = new HashMap<>();
        Map<Character, Integer> count = new HashMap<>();
        for (String word : words) {
            for (Character c : word.toCharArray()) {
                adjList.put(c, new ArrayList<>());
                count.put(c, 0);
            }
        }
        
        for (int i = 0; i < words.length - 1; i++) {
            String word1 = words[i];
            String word2 = words[i + 1];
            if (word1.length() > word2.length() && word1.startsWith(word2)) {
                return "";
            }
            for (int j = 0; j < Math.min(word1.length(), word2.length()); j++) {
                if (word1.charAt(j) != word2.charAt(j)) {
                    adjList.get(word1.charAt(j)).add(word2.charAt(j));
                    count.put(word2.charAt(j), count.get(word2.charAt(j)) + 1);
                    break;
                }
            }
        }
        
        StringBuilder sb = new StringBuilder();
        Queue<Character> queue = new LinkedList<>();
        for (Character c : count.keySet()) {
            if (count.get(c) == 0) {
                queue.add(c);
            }
        }
        while (!queue.isEmpty()) {
            Character c = queue.remove();
            sb.append(c);
            for (Character next : adjList.get(c)) {
                count.put(next, count.get(next) - 1);
                if (count.get(next) == 0) {
                    queue.add(next);
                }
            }
        }
        
        if (sb.length() < count.size()) {
            return "";
        }
        return sb.toString();
    }
}

DFS:

下面的dfs这个方法中,seen如果包含某个key, 并且是false,代表这个节点访问过,但它还有子节点没访问,标记为灰色。如果包含某个key,并且是true,说明它已经完全访问过了,标记为黑色。

class Solution {
    private Map<Character, List<Character>> adjList = new HashMap<>();
    private Map<Character, Boolean> seen = new HashMap<>();
    private StringBuilder output = new StringBuilder();

    public String alienOrder(String[] words) {
        for (String word : words) {
            for (Character c : word.toCharArray()) {
                adjList.putIfAbsent(c, new ArrayList<>());
            }
        }

        for (int i = 0; i < words.length - 1; i++) {
            String word1 = words[i];
            String word2 = words[i + 1];
            if (word1.length() > word2.length() && word1.startsWith(word2)) {
                return "";
            }

            for (int j = 0; j < Math.min(word1.length(), word2.length()); j++) {
                if (word1.charAt(j) != word2.charAt(j)) {
                    adjList.get(word2.charAt(j)).add(word1.charAt(j));
                    break;
                }
            }
        }

        for (Character c : adjList.keySet()) {
            boolean result = dfs(c);
            if (!result) return "";
        }

        if (output.length() < adjList.size()) {
            return "";
        }
        return output.toString();
    }

    private boolean dfs(Character c) {
        if (seen.containsKey(c)) {
            return seen.get(c);
        }
        seen.put(c, false);
        for (Character next : adjList.get(c)) {
            boolean result = dfs(next);
            if (!result) return false;
        }
        seen.put(c, true);
        output.append(c);
        return true;
    }
}
tags: LeetCode