269. 火星词典
现有一种使用英语字母的火星语言,这门语言的字母顺序与英语顺序不同。
给你一个字符串列表 words ,作为这门语言的词典,words 中的字符串已经 按这门新语言的字母顺序进行了排序 。
请你根据该词典还原出此语言中已知的字母顺序,并 按字母递增顺序 排列。若不存在合法字母顺序,返回 "" 。若存在多种可能的合法字母顺序,返回其中 任意一种 顺序即可。
字符串 s 字典顺序小于 字符串 t 有两种情况:
- 在第一个不同字母处,如果
s中的字母在这门外星语言的字母顺序中位于t中字母之前,那么s的字典顺序小于t。 - 如果前面
min(s.length, t.length)字母都相同,那么s.length < t.length时,s的字典顺序也小于t。
示例 1:
输入: words = ["wrt","wrf","er","ett","rftt"]
输出: "wertf"
示例 2:
输入: words = ["z","x"]
输出: "zx"
示例 3:
输入: words = ["z","x","z"]
输出: ""
解释: 不存在合法字母顺序,因此返回 "" 。
提示:
1 <= words.length <= 1001 <= words[i].length <= 100words[i]仅由小写英文字母组成
/**
* @param {string[]} words
* @return {string}
*/
var alienOrder = function(words) {
const inDegree = new Map()
for (let i = 0; i < words.length; i++) {
const word = words[i];
for (const ch of word) {
if (!inDegree.has(ch)) {
inDegree.set(ch, 0);
}
}
}
const graph = new Map();
for (let i = 1; i < words.length; i++) {
const pre = words[i - 1];
const preLen = pre.length;
const next = words[i];
const nextLen = next.length;
const len = Math.min(preLen, nextLen)
let j = 0;
while (j < len) {
if (pre[j] != next[j]) {
if (!graph.has(pre[j])) {
graph.set(pre[j], new Set());
}
if(!graph.get(pre[j]).has(next[j])) {
graph.get(pre[j]).add(next[j]);
inDegree.set(next[j], inDegree.get(next[j]) + 1);
}
break;
}
j++;
}
if (j === len && preLen > nextLen) {
return '';
}
}
const queue = [];
for (const [key, value] of inDegree) {
if (value === 0) {
queue.push(key);
}
}
const result = [];
while (queue.length) {
const node = queue.shift();
result.push(node);
const nextSet = graph.get(node);
if (!nextSet) {
continue;
}
for (const ch of nextSet) {
inDegree.set(ch, inDegree.get(ch) - 1);
if (inDegree.get(ch) === 0) {
queue.push(ch);
}
}
}
return result.length === inDegree.size ? result.join('') : '';
};