给定一个字符串列表 words ,作为这门语言的词典,words 中的字符串已经 按这门新语言的字母顺序进行了排序 。
var alienOrder = function (words) {
var c = 0;
var set = new Set(words.join('').split(''));
// 收集字母间大小关系
var larger = new Map(); // w: [e,r,t,f]
for (var l of set) {
larger.set(l, new Set());
}
while (c < words.length - 1) {
var pre = words[c];
var after = words[c + 1];
for (var i = 0; i < pre.length; i++) {
if (i >= after.length) return '';
if (pre[i] !== after[i]) {
if (larger.get(pre[i]).has(after[i])) return '';
larger.get(after[i]).add(pre[i]);
break;
}
}
c += 1;
}
var res = [];
var loop = false; // 是否有环的标记
var arr = new Array(26).fill(false);
function f(n, path = new Set()) {
// f拓扑排序
if (loop) return;
if (path.has(n)) {
loop = true;
return;
}
path.add(n); // 记录当前遍历路径,以监测是否有环。
var index = n.charCodeAt(0) - 'a'.charCodeAt(0);
if (!arr[index]) {
if (larger.get(n).size === 0) {
// 找到最小的字母,直接压入结果并返回。
res.push(n);
arr[index] = true;
return;
}
for (var i of larger.get(n)) {
f(i, path);
}
arr[index] = true;
res.push(n);
}
path.devare(n); // 回溯
}
for (var i of set) {
f(i);
}
return loop ? '' : res.join(''); // 有环返回空字符串,无环返回结果。
};