import java.util.*;
class Solution {
public static void main(String[] args) {
Solution solution = new Solution();
String str = solution.alienOrder(new String[]{
"wrt", "wrf", "er", "ett", "rftt"
});
System.out.println(str);
}
public String alienOrder(String[] words) {
for (int i = 0; i < 26; i++) {
children[i] = new ArrayList<>();
parent[i] = new ArrayList<>();
}
int p = -1;
for (int i = 0; i < words.length && valid; i++) {
char ch = words[i].charAt(0);
if (p != -1 && p != ch - 'a') {
addEdge((char)(p+'a'), ch);
} else {
// do nothing since no parent
}
p = ch - 'a';
}
for (int i = 0; i < words.length && valid; i++) {
build(words[i]);
}
String str = bfs();
return str;
}
public String bfs() {
if (!valid) {
return "";
}
StringBuilder sb = new StringBuilder();
boolean[] visited = new boolean[26];
ArrayDeque<Integer> arrayDeque = new ArrayDeque<>();
LinkedList<Integer> list = new LinkedList<>();
for (int i = 0; i < 26; i++) {
if (children[i].isEmpty() && dict[i]) {
arrayDeque.add(i);
visited[i] = true;
list.addFirst(i);
}
}
while (!arrayDeque.isEmpty()) {
int curr = arrayDeque.poll();
for (int p : parent[curr]) {
if (!visited[p]) {
arrayDeque.add(p);
visited[p] = true;
list.addFirst(p);
}
}
}
boolean[] used = new boolean[26];
while(!list.isEmpty()) {
int curr = list.poll();
sb.append((char)(curr+'a'));
used[curr] = true;
}
for (int i = 0; i<26;i++){
if(dict[i] && !used[i]) {
sb.append((char)(i+'a'));
}
}
return sb.toString();
}
public void build(String str) {
TrieNode curr = dummy;
for (int j = 0; j < str.length() && valid; j++) {
char ch = str.charAt(j);
curr.addChild(ch);
curr = curr.getChild(ch);
dict[ch - 'a'] = true;
}
}
boolean[] dict = new boolean[26];
TrieNode dummy = new TrieNode(' ');
List<Integer>[] parent = new ArrayList[26];
List<Integer>[] children = new ArrayList[26];
/**
* ch1 是ch2的祖先
*
* @param ch1
* @param ch2
* @return
*/
boolean isAncestor(char ch1, char ch2) {
boolean[] visited = new boolean[26];
ArrayDeque<Integer> arrayDeque = new ArrayDeque<>();
arrayDeque.add(ch1 - 'a');
visited[ch1 - 'a'] = true;
while (!arrayDeque.isEmpty()) {
int curr = arrayDeque.poll();
if (curr == ch2 - 'a') {
return true;
}
for (int child : children[curr]) {
if (!visited[child]) {
arrayDeque.add(child);
visited[child] = true;
}
}
}
return false;
}
boolean valid = true;
public void addEdge(char parentCh, char ch){
if (ch == parentCh) {
// 祖先節點和子節點一樣,則不需要
} else if (isAncestor(ch, parentCh)) {
valid = false;
}
// 否則
else if (isAncestor(parentCh, ch)) {
// 關係已經存在, 忽略
} else {
// 加一個關係
children[parentCh].add(ch - 'a');
parent[ch - 'a'].add(parentCh - 'a');
}
}
class TrieNode {
char ch;
TreeMap<Integer, TrieNode> map = new TreeMap<>();
public void addChild(char ch) {
TrieNode parentNode = map.lastEntry() != null ? map.lastEntry().getValue() : null;
// add a trie node;
TrieNode node = getChild(ch);
if (node != null) {
return;
}
node = new TrieNode(ch);
map.put(ch - 'a', node);
// 構建圖關係
if (map.size() == 1) {
//沒有關係,忽略
} else {
// 構建關係
addEdge(parentNode.ch, ch);
}
}
public TrieNode getChild(char ch) {
return map.get(ch - 'a');
}
public TrieNode(char ch) {
this.ch = ch;
map = new TreeMap<>();
}
}
}