-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy path0269-alien-dictionary.cpp
260 lines (212 loc) · 8.48 KB
/
0269-alien-dictionary.cpp
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
/*
Problem: LeetCode 269 - Alien Dictionary
Description:
Given a list of words in the alien language, find the order of the characters in this language.
The alien language is represented by a given dictionary, which will have words in an arbitrary order.
Each word consists of lowercase letters ('a' to 'z') and will not have duplicate characters.
It is guaranteed that no two words in the dictionary have the same ordering of letters.
If the order is invalid, return an empty string. There may be multiple valid orderings, you should return the smallest one in lexicographical order.
Intuition:
This problem can be solved using topological sorting. The given dictionary represents the relationship between characters in the alien language. The order of characters in the alien language can be determined by their relative positions in the words of the dictionary.
Approach:
1. Create a graph to represent the relationship between characters in the alien language.
2. Traverse the dictionary and add edges to the graph based on the order of characters in adjacent words.
3. Perform topological sorting on the graph to get the order of characters in the alien language.
4. Return the result as a string.
Time Complexity:
The time complexity of the solution is O(N), where N is the total number of characters in all the words in the dictionary. The reason is that we iterate through each character once to build the graph and perform topological sorting.
Space Complexity:
The space complexity of the solution is O(1) since we are using a fixed-size array of size 26 to represent the graph.
Topological Sorting:
- Intuition: Topological sorting is used to find the linear order of vertices in a directed acyclic graph (DAG) such that for every directed edge (u, v), vertex u comes before v in the ordering.
- Approach: We use a depth-first search (DFS) based approach to perform topological sorting. We start from a source vertex (a vertex with no incoming edges) and visit its neighbors recursively. After visiting all the neighbors, we add the current vertex to the result stack. The result stack will contain the vertices in the correct order.
*/
class Solution {
public:
string alienOrder(vector<string> &words) {
// Initialize the graph and indegree array
vector<vector<bool>> graph(26, vector<bool>(26, false));
vector<int> indegree(26, -1);
// Step 1: Build the graph and calculate indegrees
buildGraph(words, graph, indegree);
// Step 2: Perform topological sorting using DFS
string result = topologicalSort(graph, indegree);
return result;
}
private:
// Helper function to build the graph and calculate indegrees
void buildGraph(vector<string> &words, vector<vector<bool>> &graph, vector<int> &indegree) {
for (string &word : words) {
for (char c : word) {
indegree[c - 'a'] = 0;
}
}
for (int i = 1; i < words.size(); i++) {
string prevWord = words[i - 1];
string currWord = words[i];
int len = min(prevWord.length(), currWord.length());
for (int j = 0; j < len; j++) {
char prevChar = prevWord[j];
char currChar = currWord[j];
if (prevChar != currChar) {
if (!graph[prevChar - 'a'][currChar - 'a']) {
graph[prevChar - 'a'][currChar - 'a'] = true;
indegree[currChar - 'a']++;
}
break;
}
}
}
}
// Helper function for topological sorting using DFS
string topologicalSort(vector<vector<bool>> &graph, vector<int> &indegree) {
string result = "";
stack<char> st;
for (int i = 0; i < 26; i++) {
if (indegree[i] == 0) {
st.push('a' + i);
}
}
while (!st.empty()) {
char curr = st.top();
st.pop();
result += curr;
for (int i = 0; i < 26; i++) {
if (graph[curr - 'a'][i]) {
indegree[i]--;
if (indegree[i] == 0) {
st.push('a' + i);
}
}
}
}
// If there are still edges in the graph, it means there is a cycle
for (int i = 0; i < 26; i++) {
if (indegree[i] > 0) {
return "";
}
}
return result;
}
};
/*
// Another DFS solution
class Solution {
public:
string alienOrder(vector<string>& words) {
unordered_map<char, vector<char>> graph;
unordered_map<char, int> indegree;
// Step 1: Build the graph and calculate indegrees
for (string& word : words) {
for (char c : word) {
indegree[c] = 0;
}
}
for (int i = 1; i < words.size(); i++) {
string prevWord = words[i - 1];
string currWord = words[i];
int len = min(prevWord.length(), currWord.length());
for (int j = 0; j < len; j++) {
char prevChar = prevWord[j];
char currChar = currWord[j];
if (prevChar != currChar) {
graph[prevChar].push_back(currChar);
indegree[currChar]++;
break;
}
}
}
// Step 2: Perform topological sorting using DFS
string result;
stack<char> st;
for (const auto& entry : indegree) {
if (entry.second == 0) {
st.push(entry.first);
}
}
while (!st.empty()) {
char curr = st.top();
st.pop();
result += curr;
for (char next : graph[curr]) {
if (--indegree[next] == 0) {
st.push(next);
}
}
}
return result.size() == indegree.size() ? result : "";
}
};
*/
/*
// BFS Solution
class Solution {
public:
string alienOrder(vector<string>& words) {
vector<vector<bool>> adjList(26, vector<bool>(26, false));
vector<int> indegree(26, -1);
// Step 1: Build the adjacency list and calculate indegrees
buildGraph(words, adjList, indegree);
// Step 2: Perform topological sorting using BFS
string result = topologicalSort(adjList, indegree);
return result;
}
private:
// Helper function to build the adjacency list and calculate indegrees
void buildGraph(vector<string>& words, vector<vector<bool>>& adjList, vector<int>& indegree) {
// Initialize the indegree for all characters
for (string& word : words) {
for (char c : word) {
indegree[c - 'a'] = 0;
}
}
// Compare adjacent words to build the adjacency list and update indegrees
for (int i = 1; i < words.size(); i++) {
string prevWord = words[i - 1];
string currWord = words[i];
int len = min(prevWord.length(), currWord.length());
for (int j = 0; j < len; j++) {
char prevChar = prevWord[j];
char currChar = currWord[j];
if (prevChar != currChar) {
if (!adjList[prevChar - 'a'][currChar - 'a']) {
adjList[prevChar - 'a'][currChar - 'a'] = true;
indegree[currChar - 'a']++;
}
break;
}
}
}
}
// Helper function for topological sorting using BFS
string topologicalSort(vector<vector<bool>>& adjList, vector<int>& indegree) {
string result = "";
queue<char> q;
// Add characters with indegree 0 to the queue
for (int i = 0; i < 26; i++) {
if (indegree[i] == 0) {
q.push('a' + i);
}
}
// Perform BFS to get the topological ordering
while (!q.empty()) {
char curr = q.front();
q.pop();
result += curr;
for (int i = 0; i < 26; i++) {
if (adjList[curr - 'a'][i]) {
indegree[i]--;
if (indegree[i] == 0) {
q.push('a' + i);
}
}
}
}
// If there are still edges in the graph, it means there is a cycle
if (result.length() != 26) {
return "";
}
return result;
}
};
*/