拓扑排序关键:
- 无环有向图Directed Acyclic Graph (DAG)
- 用backtracking或stack从后往前
- 记录访问过的节点避免重复访问
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 ofnon-emptywords from the dictionary, wherewords are sorted lexicographically by the rules of this new language. Derive the order of letters in this language.
Example 1:
Given the following words in dictionary,
[
"wrt",
"wrf",
"er",
"ett",
"rftt"
]
The correct order is:"wertf"
.
Example 2:
Given the following words in dictionary,
[
"z",
"x"
]
The correct order is:"zx"
.
Example 3:
Given the following words in dictionary,
[
"z",
"x",
"z"
]
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.
S: Topological Sort
- 根据前后两个单词第一个不同的字母构建有向边,从而组成图。注意无序节点也要加入图
- 对图进行拓扑排序,用visited记录访问过的节点,用ancestor记录当前路径的前后关系判断是否成环
class Solution {
public:
string alienOrder(vector<string>& words) {
if (words.size() == 1) {
return words[0];
}
unordered_map<char, unordered_set<char>> map;
for (int i = 1; i < words.size(); ++i) {
makeGraph(map, words[i - 1], words[i]);
}
vector<bool> visited(26);
vector<bool> ancestor(26);
string result = "";
string test = "";
for (const auto& i : map) {
test += i.first;
if (!dfs(map, i.first, result, visited, ancestor)){
return "";
}
}
return result;
}
private:
void makeGraph(unordered_map<char, unordered_set<char>>& map, string word1, string word2) {
int idx = 0;
while (idx < word1.size() && idx < word2.size() && word1[idx] == word2[idx]) {
addChar(map, word1[idx]);
idx++;
}
if (idx < word1.size() && idx < word2.size()) {
map[word1[idx]].insert(word2[idx]);
addChar(map, word2[idx]);
idx++;
}
for (int i = idx; i < word1.size(); ++i) {
addChar(map, word1[idx]);
}
for (int i = idx; i < word2.size(); ++i) {
addChar(map, word2[idx]);
}
}
void addChar(unordered_map<char, unordered_set<char>>& map, char a) {
if (map.find(a) == map.end()) {
map[a] = unordered_set<char>{};
}
}
bool dfs(unordered_map<char, unordered_set<char>>& map, char letter, string& result,
vector<bool>& visited, vector<bool>& ancestor) {
if (ancestor[letter - 'a']) {
return false;
}
if (visited[letter - 'a']) {
return true;
}
visited[letter - 'a'] = true;
ancestor[letter - 'a'] = true;
for (char i : map[letter]) {
if (!dfs(map, i, result, visited, ancestor)) {
return false;
}
}
ancestor[letter - 'a'] = false;
result = letter + result;
return true;
}
};