public String alienOrder(String[] words) {
//because the char has a topological order, we record how many char to current char
// a (b ,c, d) after it
// b (c ,d ) after it
Map<Character, Set<Character>> map = new HashMap<>();
Map<Character, Integer> indegree = new HashMap<>();
for(String w: words){
for(Character c : w.toCharArray()){
indegree.putIfAbsent(c,0);
}
}
for(int i = 0 ; i < words.length -1; ++i){
String current = words[i];
String next = words[i+1];
if(current.length() > next.length() && current.startsWith(next)){
return "";
}
int l = Math.min(current.length() , next.length());
for(int j = 0; j < l; ++j){
char c1 = current.charAt(j);
char c2 = next.charAt(j);
if( c1 != c2 ){
Set<Character> set = map.computeIfAbsent(c1, k -> new HashSet<Character>());
if(!set.contains(c2)){
set.add(c2);
indegree.put(c2, indegree.get(c2)+1);
}
break;
}
}
}
//topo sorting
Queue<Character> queue = new LinkedList<>();
StringBuilder sb = new StringBuilder();
for(Character c : indegree.keySet()){
if(indegree.get(c) == 0){
queue.offer(c);
}
}
while(!queue.isEmpty()){
Character current = queue.poll();
sb.append(current);
if(!map.containsKey(current)) continue;
for(Character next: map.get(current)){
int count = indegree.get(next);
count--;
indegree.put(next, count);
if(count == 0){
queue.offer(next);
}
}
}
if(sb.length() != indegree.size()) return "";
return sb.toString();
}
本题因为要寻找一个规律, 所以想到做topological sorting.
所有topo排序的问题都要计算Indegree。 然后用一个queue来遍历这个Indegree的表单。
为了维护这个indegree的遍历,我们要生成一个map,记录每个character之后会出现什么character
所以我们要维护两个表。
一个是Map<Character, Set<Character>>用来记录每个单词可以到达其他的什么单词。
一个是Map<Character, Integer> indegree的表,用来记录每个单词的入度。
此题难点:
如何判断当前的输入不合法?
1. 单词不一样长的情况- 第二个单词长而且第一个单词以第二个单词开头
“wrtabcde”
"wrt"
2. 遍历结果并没有包括Indegree里面所有的字母。 也就是说Indegree里面还有不为0的数。
例如
“z”
"w"
"z"
这个例子中 z和w的indegree都是1.整个表中没有入度为0的点。 所以输入不合法
https://leetcode.com/problems/alien-dictionary/description/