269. Alien Dictionary
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.
Example 1:
Input:
[
"wrt",
"wrf",
"er",
"ett",
"rftt"
]
Output: "wertf"
Example 2:
Input:
[
"z",
"x"
]
Output: "zx"
Example 3:
Input:
[
"z",
"x",
"z"
]
Output: ""
Explanation: The order is invalid, so return "".
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.
// BFS
string alienOrder(vector<string>& words) {
set<pair<char, char> > st; // character relation pairs
unordered_set<char> ch; // occurrence of letters
vector<int> in(26, 0); // indegree
queue<char> q; // BFS
string res;
for (string& w : words) ch.insert(w.begin(), w.end());
for (int i = 0; i < words.size() - 1; ++i) {
int len = min(words[i].length(), words[i + 1].length()), j = 0;
for (; j < len; ++j) {
if (words[i][j] != words[i + 1][j]) {
st.insert(make_pair(words[i][j], words[i + 1][j]));
break;
}
}
if (j == len && words[i].length() > words[i + 1].length()) return res; // return empty string
}
for (auto& p : st) ++in[p.second - 'a'];
for (auto& c : ch) {
if (in[c - 'a'] == 0) {
q.push(c);
res += c;
}
}
while (!q.empty()) {
char c = q.front(); q.pop();
for (auto& p : st) {
if (p.first == c) {
if (--in[p.second - 'a'] == 0) {
q.push(p.second);
res += p.second;
}
}
}
}
return res.length() == ch.size() ? res : "";
}
// BFS
string alienOrder(vector<string>& words) {
unordered_set<string> st; // hashset of strings with len = 2, str[0] -> str[1]
unordered_set<char> ch; // occurrence of all characters
vector<int> in(26, 0); // indegrees of each characters
queue<char> q; // BFS queue
string res; // final result
// Add all chars in each word to ch
for (const auto& word : words) ch.insert(word.begin(), word.end());
// Find the character relations
for (int i = 0; i < words.size() - 1; ++i) {
int len = min(words[i].length(), words[i + 1].length()), j = 0;
for (; j < len; ++j) {
if (words[i][j] != words[i + 1][j]) {
string tmp = string(2, ' ');
tmp[0] = words[i][j];
tmp[1] = words[i + 1][j];
st.insert(tmp);
break;
}
}
if (j == len && words[i].length() > words[i + 1].length()) return res; // return empty string
}
// Calculate indegrees for each char
for (const string& str : st) ++in[str[1] - 'a'];
// Add char with 0 indegree to BFS queue
for (const char& c : ch) {
if (in[c - 'a'] == 0) {
q.push(c);
res += c;
}
}
// BFS
while (!q.empty()) {
char c = q.front(); q.pop();
for (const string& str : st) {
if (str[0] == c) {
if (--in[str[1] - 'a'] == 0) {
q.push(str[1]);
res += str[1];
}
}
}
}
return res.length() == ch.size() ? res : "";
}
// BFS Topological Sort
string alienOrder(vector<string>& words) {
string res;
if (words.empty()) return res;
unordered_map<char, unordered_set<char> > graph;
unordered_map<char, int> indegree;
// Initialization
for (auto& word : words) {
for (char ch : word) {
indegree[ch] = 0;
}
}
// Build adjacency list
for (int i = 0; i < words.size() - 1; ++i) {
string cur = words[i], next = words[i + 1];
for (int j = 0; j < min(cur.length(), next.length()); ++j) {
char c1 = cur[j], c2 = next[j];
if (c1 != c2) {
if (!graph[c1].count(c2)) {
graph[c1].insert(c2);
++indegree[c2];
}
break;
}
}
}
// Use queue to do BFS
queue<char> q;
for (auto it = indegree.begin(); it != indegree.end(); ++it) {
if (it->second == 0) {
q.push(it->first);
}
}
while (!q.empty()) {
char c = q.front(); q.pop();
res += c;
for (auto it = graph[c].begin(); it != graph[c].end(); ++it) {
if (--indegree[*it] == 0) {
q.push(*it);
}
}
}
return (res.length() != indegree.size()) ? "" : res;
}
// DFS Topological Sort
bool dfs(vector<vector<bool> >& graph, vector<bool>& visited, int idx, string& res) {
if (!graph[idx][idx]) return true;
visited[idx] = true;
for (int i = 0; i < 26; ++i) {
if (i == idx || !graph[idx][i]) continue;
if (visited[i] || !dfs(graph, visited, i, res)) return false;
}
visited[idx] = false;
graph[idx][idx] = false;
res += ('a' + idx);
return true;
}
string alienOrder(vector<string>& words) {
// graph[i][i] records occurrence of char i; graph[i][j] records the order pair
vector<vector<bool> > graph(26, vector<bool>(26, false));
vector<bool> visited(26, false);
string res;
// Record the occurrence of chars
for (string& word : words) {
for (char ch : word) {
graph[ch - 'a'][ch - 'a'] = true;
}
}
// Build letter order pairs
for (int i = 0; i < words.size() - 1; ++i) {
int len = min(words[i].length(), words[i + 1].length()), j = 0;
for (; j < len; ++j) {
if (words[i][j] != words[i + 1][j]) {
graph[words[i][j] - 'a'][words[i + 1][j] - 'a'] = true;
break;
}
}
if (j == len && words[i].length() > words[i + 1].length()) return "";
}
// DFS
for (int i = 0; i < 26; ++i) {
if (!dfs(graph, visited, i, res)) return "";
}
reverse(res.begin(), res.end());
return res;
}
Last updated
Was this helpful?