🌈【LeetCode 114. 外星文字典 】- JavaScript(拓扑排序+dfs)

129 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情


说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)

作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金

GitHub:P-J27、 CSDN:PJ想做前端攻城狮

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


【LeetCode 114. 外星文字典 】- JavaScript(拓扑排序+dfs)

题目描述

现有一种使用英语字母的外星文语言,这门语言的字母顺序与英语顺序不同。

给定一个字符串列表 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"

拓扑排序

思路分析:

拓扑排序的思路:首先我们要从words中还原出字典序,words也有可能没有按照字典序来排列,那就得要判断是不是按照字典序,而且字典序有两种而且两种都要检查,我们可以先取出来所有的第一个,压缩排序,再取出来相似的第二个,再进行压缩排序·,最后的就是结果。于是可以使用拓扑排序的思路,并且搭配上dfs来进行搜索。具体实现步骤如下:

  • 我们先收集字母间大小关系
  • 在进行DFS拓扑排序
  • 通过path来判断是否存在环的情况,再非环情况下搜索最小的
  • 最后如果有环就返回空串,否则返回path即可。

还有两个注意点:

  • 注意defaultdict如果key不初始化是不存在的,所以要有in_v[words[i][j]] = in_v[words[i][j]]
  • 对于["abc","ab"]情形,需要判断前面的“ab”相等,但是后面的长度比前面小,直接返回不合法
var alienOrder = function(words) {
    let c = 0;
    let letters = new Set(words.join('').split(''));
    
    let larger = new Map();
    for (let l of letters) {
        larger.set(l, new Set());
    }
    while (c < words.length-1) {
        let pre = words[c];
        let after = words[c+1];
        for (let 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;
    }
    let res = [];
    let loop = false;
    let visited = new Array(26).fill(false);
    function dfs(n, path = new Set()) {
        if (loop) return;
        if (path.has(n)) {
            loop = true;
            return;
        }
        path.add(n);
        let index = n.charCodeAt(0) - 'a'.charCodeAt(0);
        if (!visited[index]) {
            if (larger.get(n).size === 0) {
                res.push(n);
                visited[index] = true;
                return;
            }
            for (let i of larger.get(n)) {
                dfs(i, path);
            }
            visited[index] = true;
            res.push(n);
        }
        path.delete(n); 
    }
    for (let i of letters) {
        dfs(i);
    }
    return loop ? '' : res.join(''); 
};

思考

有一说一,我是菜鸡,这题写了好多遍才A出来,我确实之前还不会拓扑排序,知道知识点,就是没敲过。我是菜鸡,o(╥﹏╥)o。。👀🤞


感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。

写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤