-
Notifications
You must be signed in to change notification settings - Fork 820
/
AlienDictionary.java
126 lines (116 loc) · 3.62 KB
/
AlienDictionary.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/* (C) 2024 YourCompanyName */
package depth_first_search;
import java.util.*;
/**
* Created by gouthamvidyapradhan on 02/12/2017. 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.
*
* <p>Example 1: Given the following words in dictionary,
*
* <p>[ "wrt", "wrf", "er", "ett", "rftt" ] The correct order is: "wertf".
*
* <p>Example 2: Given the following words in dictionary,
*
* <p>[ "z", "x" ] The correct order is: "zx".
*
* <p>Example 3: Given the following words in dictionary,
*
* <p>[ "z", "x", "z" ] The order is invalid, so return "".
*
* <p>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.
*
* <p>Solution: Build a graph with with character links and perform a topological sort. Topological
* sort can be performed only on a DAG hence if there is a cycle immediately return empty string
*/
public class AlienDictionary {
private Map<Character, List<Character>> graph;
private Set<Character> done;
private Set<Character> visited;
private Stack<Character> toposort;
/**
* Main method
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
String[] words = {"z", "x", "z"};
System.out.println(new AlienDictionary().alienOrder(words));
}
public String alienOrder(String[] words) {
graph = new HashMap<>();
done = new HashSet<>();
visited = new HashSet<>();
toposort = new Stack<>();
boolean[] A = new boolean[26];
for (int i = 0; i < words.length - 1; i++) {
for (int j = 0, l = Math.min(words[i].length(), words[i + 1].length()); j < l; j++) {
if (words[i].charAt(j) != words[i + 1].charAt(j)) {
graph.putIfAbsent(words[i].charAt(j), new ArrayList<>());
graph.get(words[i].charAt(j)).add(words[i + 1].charAt(j));
break;
}
}
}
for (String w : words) {
for (int i = 0, l = w.length(); i < l; i++) {
A[w.charAt(i) - 'a'] = true;
}
}
for (char c : graph.keySet()) {
if (!done.contains(c)) {
if (!dfs(c)) return "";
}
}
StringBuilder sb = new StringBuilder();
while (!toposort.isEmpty()) {
sb.append(toposort.pop());
}
// Add remaining elements. This can come in any order.
String result = sb.toString();
StringBuilder remaining = new StringBuilder();
for (int i = 0; i < 26; i++) {
if (A[i]) {
char c = (char) (i + 'a');
boolean found = false;
for (char r : result.toCharArray()) {
if (r == c) {
found = true;
break;
}
}
if (!found) {
remaining.append(c);
}
}
}
return result.concat(remaining.toString().trim());
}
/**
* Dfs to toposort
*
* @param u
* @return
*/
private boolean dfs(char u) {
done.add(u);
visited.add(u);
List<Character> children = graph.get(u);
if (children != null) {
for (char c : children) {
if (visited.contains(c)) return false; // check cycle
if (!done.contains(c)) {
boolean status = dfs(c);
if (!status) return false;
}
}
}
toposort.push(u);
visited.remove(u);
return true;
}
}