build graph O(mn) time
topological sort O(v+e) time
这里[“ab”, “abc”]以及[“z”, “z”]都是合法的,返回任一结果即可,但是[“abc”, “ab”]是非法的,必须返回空串
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
| class Solution { public: string alienOrder(vector<string>& words) { string u; for (auto v : words) { for (auto c : v) { if (!g.count(c)) { g[c] = {}; } } int n = min(u.length(), v.length()), i = 0; for (; i < n; ++i) { if (u[i] != v[i]) { g[u[i]].insert(v[i]); break; } } if (i == n && u.length() > v.length()) return ""; u.swap(v); } visited.resize(128); for (auto [c, _] : g) { if (!isAcyclic(c)) return ""; } return string(rbegin(s), rend(s)); }
bool isAcyclic(char u) { if (visited[u]) return visited[u] == 1; visited[u] = -1; for (auto v : g[u]) { if (!isAcyclic(v)) return false; } s += u; visited[u] = 1; return true; }
string s; unordered_map<char, unordered_set<char>> g; vector<char> visited; };
|
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
| class Solution { public: string alienOrder(vector<string>& words) { if (words.size() == 1) return words[0]; auto cmp = [](const string &a, const string &b) {return a.length() < b.length();}; int n = words.size(), m = max_element(begin(words), end(words), cmp)->length(); vector<bool> isOrdered(n - 1); for (int j = 0; j < m; ++j) { for (int i = 0; i < n - 1; ++i) { if (!isOrdered[i]) { if (words[i].length() <= j) { isOrdered[i] = true; } else if (words[i][j] != words[i + 1][j]) { isOrdered[i] = true; g[words[i][j]].insert(words[i + 1][j]); if (g.count(words[i + 1][j]) == 0) { g[words[i + 1][j]] = {}; } } } if (j < words[i].length() && g.count(words[i][j]) == 0) { g[words[i][j]] = {}; } if (j < words[i + 1].length() && g.count(words[i + 1][j]) == 0) { g[words[i + 1][j]] = {}; } } } visited.resize(128); for (auto &&p : g) { if (!ts(p.first)) return ""; } string res; while (!s.empty()) { res += s.top(); s.pop(); } return res; }
bool ts(char ch) { if (visited[ch] == 1) return true; if (visited[ch] == -1) return false; visited[ch] = -1; for (auto &&c : g[ch]) { if (!ts(c)) return false; } s.push(ch); visited[ch] = 1; return true; }
vector<int> visited; stack<char> s; unordered_map<char, unordered_set<char>> g; };
|
followup: All results of Alien Dictionary
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
| class Solution { public: vector<string> alienOrder(vector<string> words) { string u; for (auto v : words) { for (char c : v) { if (g.count(c) == 0) { g[c] = {}; } } int len = min(u.length(), v.length()), i = 0; for (; i < len; ++i) { if (u[i] != v[i]) { g[u[i]].insert(v[i]); break; } } if (i == len && u.length() > v.length()) return {}; u.swap(v); } n = g.size(); visited.resize(128); dfs(0); return res; }
void dfs(int b) { if (b == n) { res.push_back(s); return; } for (auto [c, _] : g) { if (visited[c] || !isValid(c)) continue; visited[c] = true; s += c; dfs(b + 1); s.pop_back(); visited[c] = false; } }
bool isValid(char c) { for (char t : s) { if (g[c].count(t)) return false; } return true; }
int n; vector<bool> visited; string s; vector<string> res; unordered_map<char, unordered_set<char>> g; };
int main() { Solution sol; for (auto s : sol.alienOrder({"wrt","wrf","er","ett","rftt"})) { cout<<s<<endl; } return 0; }
|