拓扑排序-269火星词典

301 阅读1分钟

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 <= 100
  • 1 <= words[i].length <= 100
  • words[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('') : '';
};