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:
- You may assume all letters are in lowercase.
- You may assume that if a is a prefix of b, then a must appear before b in the given dictionary.
- If the order is invalid, return an empty string.
- There may be multiple valid order of letters, return any one of them is fine.
public class Solution {
public String alienOrder(String[] words) {
HashMap<Character, Set<Character>> map = new HashMap<Character, Set<Character>>();//<c, char after c>
HashMap<Character, Integer> degree = new HashMap<Character, Integer>();//<c, # of char before c>
StringBuilder res = new StringBuilder();
//initialize degree map
for(int i = 0; i < words.length; i++){
char[] word = words[i].toCharArray();
for(int j = 0; j < word.length; j++){
degree.put(word[j], 0);
}
}
//compare adjacent string & fill map
for(int i = 0; i < words.length - 1; i++){
String cur = words[i];
String next = words[i + 1];
int len = Math.min(cur.length(), next.length());
for(int j = 0; j < len; j++){
char c1 = cur.charAt(j);
char c2 = next.charAt(j);
if(c1 != c2){
Set<Character> set = new HashSet<Character>();//watch 'Set' declaration
if(map.containsKey(c1))set = map.get(c1);
if(!set.contains(c2)){
set.add(c2);
map.put(c1, set);
degree.put(c2, degree.get(c2) + 1);
}
break;//rest comparision is meaningless & not record it!
}
}
}
//BFS - use Queue to pop char in order
Queue<Character> queue = new LinkedList<Character>();
for(char c: degree.keySet()){
if(degree.get(c)==0){
queue.add(c);//eg:[zx,zy], c: z,x
}
}
while(!queue.isEmpty()){
char cur = queue.remove();
res.append(cur);
if(map.containsKey(cur)){
for(char c: map.get(cur)){
degree.put(c, degree.get(c) - 1); //topological sort
if(degree.get(c) == 0){
queue.add(c);//add next char
}
}
}
}
//avoid loops. only < possible -- eg: ["qd","ab"] res = qa
if(res.length() != degree.size())return "";
return res.toString();
}
}