Skip to content

Instantly share code, notes, and snippets.

@jianminchen
Created May 4, 2018 18:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jianminchen/d12cfa2b9e6654eb743e7ef5182b6bcc to your computer and use it in GitHub Desktop.
Save jianminchen/d12cfa2b9e6654eb743e7ef5182b6bcc to your computer and use it in GitHub Desktop.
Alien dictionary - Java code with some improvement
Study the analysis from the blog:
https://segmentfault.com/a/1190000003795463
May 4, 2018
I like to build a good habit to work the analysis. It is the important to understand the analysis
word by word. Highlight key points.
新建一个AlienChar数据结构重写,只用一个Map作为Graph自身
public class Solution {
public String alienOrder(String[] words) {
Map<Character, AlienChar> graph = new HashMap<Character, AlienChar>();
// 如果建图失败,比如有 a->b 和 b->a 这样的边,就返回false
boolean isBuildSucceed = buildGraph(words, graph);
if(!isBuildSucceed){
return "";
}
// 在建好的图中根据拓扑排序遍历
String order = findOrder(graph);
return order.length() == graph.size() ? order : "";
}
private boolean buildGraph(String[] words, Map<Character, AlienChar> graph){
HashSet<String> visited = new HashSet<String>();
// 初始化图,每个字母都初始化入度为0
initializeGraph(words, graph);
for(int wordIdx = 0; wordIdx < words.length - 1; wordIdx++){
String before = words[wordIdx];
String after = words[wordIdx + 1];
Character prev = null, next = null;
// 找到相邻两个单词第一个不一样的字母
for(int letterIdx = 0; letterIdx < before.length() && letterIdx < after.length(); letterIdx++){
if(before.charAt(letterIdx) != after.charAt(letterIdx)){
prev = before.charAt(letterIdx);
next = after.charAt(letterIdx);
break;
}
}
// 如果有环,则建图失败
if(prev != null && visited.contains(next + "" + prev)){
return false;
}
// 如果这条边没有添加过,则在图中加入这条边
if(prev != null && !visited.contains(prev + "" + next)){
addEdge(prev, next, graph);
visited.add(prev + "" + next);
}
}
return true;
}
private void initializeGraph(String[] words, Map<Character, AlienChar> graph){
for(String word : words){
for(int idx = 0; idx < word.length(); idx++){
if(!graph.containsKey(word.charAt(idx))){
graph.put(word.charAt(idx), new AlienChar(word.charAt(idx)));
}
}
}
}
private void addEdge(char prev, char next, Map<Character, AlienChar> graph){
AlienChar prevAlienChar = graph.get(prev);
AlienChar nextAlienChar = graph.get(next);
nextAlienChar.indegree += 1;
prevAlienChar.later.add(nextAlienChar);
graph.put(prev, prevAlienChar);
graph.put(next, nextAlienChar);
}
private String findOrder(Map<Character, AlienChar> graph){
StringBuilder order = new StringBuilder();
Queue<AlienChar> queue = new LinkedList<AlienChar>();
for(Character c : graph.keySet()){
if(graph.get(c).indegree == 0){
queue.offer(graph.get(c));
}
}
while(!queue.isEmpty()){
AlienChar curr = queue.poll();
order.append(curr.val);
for(AlienChar next : curr.later){
if(--next.indegree == 0){
queue.offer(next);
}
}
}
return order.toString();
}
}
class AlienChar {
char val;
ArrayList<AlienChar> later;
int indegree;
public AlienChar(char c){
this.val = c;
this.later = new ArrayList<AlienChar>();
this.indegree = 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment