Skip to content

Commit 13fd850

Browse files
committed
DaleStudy#291 Alien Dictionary
1 parent 3e184b6 commit 13fd850

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed

alien-dictionary/forest000014.java

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
# Time Complexity: O(wl)
3+
- w은 words의 길이, l은 words[i]의 길이
4+
- word 하나를 trie에 등록하는 과정 O(l)
5+
- 모든 word를 trie에 등록하는 과정 O(wl)
6+
- graph를 순회하면서 위상정렬하는 과정 O(26^2) = O(1)
7+
# Space Complexity: O(wl)
8+
- trie의 공간복잡도 O(wl)
9+
*/
10+
11+
class Solution {
12+
13+
private class TrieNode {
14+
char ch;
15+
boolean ends;
16+
List<TrieNode> children;
17+
18+
TrieNode(char ch) {
19+
this.ch = ch;
20+
children = new ArrayList<>();
21+
}
22+
}
23+
24+
public String alienOrder(String[] words) {
25+
List<List<Integer>> graph = new ArrayList<>();
26+
for (int i = 0; i < 26; i++) {
27+
graph.add(new ArrayList<>());
28+
}
29+
boolean[] visited = new boolean[26];
30+
int[] inDegree = new int[26];
31+
int[] outDegree = new int[26];
32+
Queue<Character> queue = new LinkedList<>();
33+
34+
TrieNode root = new TrieNode('.');
35+
36+
for (int i = 0; i < words.length; i++) {
37+
TrieNode curr = root;
38+
39+
for (int j = 0; j < words[i].length(); j++) {
40+
// 유효한 순서가 아님이 확실하면, 곧바로 false를 리턴한다.
41+
// 유효한 순서가 아님이 확실하지 않으면, trie에 추가하고, relation을 추가한다.
42+
// 단, words[i]의 마지막 글자라면, trie의 마지막에 ends = true를 세팅한다.
43+
44+
char ch = words[i].charAt(j);
45+
visited[ch - 'a'] = true;
46+
47+
if (curr.children.size() == 0) {
48+
curr.children.add(new TrieNode(ch));
49+
curr = curr.children.get(curr.children.size() - 1);
50+
if (j == words[i].length()) curr.ends = true;
51+
continue;
52+
}
53+
54+
char lastCh = curr.children.get(curr.children.size() - 1).ch;
55+
if (lastCh == ch) {
56+
curr = curr.children.get(curr.children.size() - 1);
57+
if (j == words[i].length() - 1) {
58+
if (!curr.children.isEmpty()) return "";
59+
else curr.ends = true;
60+
}
61+
continue;
62+
}
63+
64+
for (int p = 0; p < curr.children.size() - 1; p++) {
65+
if (curr.children.get(p).ch == ch) return "";
66+
}
67+
68+
addEdge(graph, inDegree, outDegree, lastCh, ch);
69+
curr.children.add(new TrieNode(ch));
70+
curr = curr.children.get(curr.children.size() - 1);
71+
}
72+
}
73+
74+
for (int i = 0; i < 26; i++) {
75+
if (inDegree[i] == 0 && outDegree[i] != 0) queue.offer((char)('a' + i));
76+
}
77+
78+
StringBuilder sb = new StringBuilder();
79+
80+
for (int i = 0; i < 26; i++) {
81+
if (visited[i] && inDegree[i] == 0 && outDegree[i] == 0) sb.append((char)('a' + i));
82+
}
83+
84+
while (!queue.isEmpty()) {
85+
char ch = queue.poll();
86+
sb.append(ch);
87+
88+
for (int next : graph.get(ch - 'a')) {
89+
if (--inDegree[next] == 0) queue.offer((char)('a' + next));
90+
}
91+
}
92+
93+
for (int i = 0; i < 26; i++) {
94+
if (inDegree[i] > 0) return "";
95+
}
96+
97+
return sb.toString();
98+
}
99+
100+
private boolean addEdge(List<List<Integer>> graph, int[] inDegree, int[] outDegree, char from, char to) {
101+
int sz = graph.get(from - 'a').size();
102+
for (int i = 0; i < sz; i++) {
103+
if (graph.get(from - 'a').get(i) == to - 'a') return false;
104+
}
105+
106+
graph.get(from - 'a').add(to - 'a');
107+
outDegree[from - 'a']++;
108+
inDegree[to - 'a']++;
109+
return true;
110+
}
111+
}

0 commit comments

Comments
 (0)