269. Alien Dictionary

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"

Input:
[
  "z",
  "x",
  "z"
]

Output: ""

Explanation: The order is invalid, so return "".
public String alienOrder(String[] words) {
    HashMap<Character, HashSet<Character>> map = new HashMap<>(); // chars with neighbors
    HashSet<Character> allChars = new HashSet<>();
    for(Character ch : words[0].toCharArray()) allChars.add(ch);
    for(int i = 1; i < words.length; i++) {
        String p = words[i-1], c = words[i];
        for(Character ch : c.toCharArray()) allChars.add(ch);
        for(int j = 0; j < Math.min(p.length(), c.length()); j++) {
            if(p.charAt(j) != c.charAt(j)) {
                HashSet<Character> set = map.getOrDefault(p.charAt(j), new HashSet<Character>());
                set.add(c.charAt(j));
                map.put(p.charAt(j), set);
                break;
            }
        }
    }

    HashMap<Character, Integer> inDegree = new HashMap<>();
    for(Character c : allChars) inDegree.put(c, 0);
    for(HashSet<Character> set : map.values()) {
        for(Character c : set)
            inDegree.put(c, inDegree.get(c) + 1);
    }

    Queue<Character> q = new LinkedList<>();
    for(Character c : allChars) {
        if(inDegree.get(c) == 0)
            q.offer(c);
    }

    StringBuilder sb = new StringBuilder();
    while(!q.isEmpty()) {
        char c = q.poll();
        sb.append(c);
        if(map.containsKey(c)) {
            for(Character next : map.get(c)) {
                int v = inDegree.get(next);
                inDegree.put(next, v - 1);
                if(v - 1 == 0) q.offer(next);
            }
        }
    }
    return sb.length() == allChars.size() ? sb.toString() : "";
}