跳转至

269.火星词典 (Hard)*

题目描述*

标签*

图论;拓扑排序;

思路 & 代码*

默认小写。顺序不合法则返回空串,多种合法顺序返回任一。

相邻两个字符串找到第一个不同的字符就得到了这两个字符的关系。先根据这个顺序关系构建图,然后再进行拓扑排序输出。从来没实现过拓扑排序,也比较简单,就是每次选入度为 0 的节点移除,知道访问到所有结点或不存在入度为 0 的节点。

class Solution {
private:
    size_t letters = 26;
public:
    string alienOrder(vector<string>& words) {
        int n = words.size();
        if(n == 0) {
            return "";
        }
        // 构造图的邻接表,入度表
        vector<int> in_degree(letters, 0);
        vector<unordered_set<char>> graph(letters, unordered_set<char>());
        unordered_set<char> seen_letters(words[n - 1].begin(), words[n - 1].end());
        for(int i = 0; i < n - 1; i++) {
            seen_letters.insert(words[i].begin(), words[i].end());
            int idx = 0;
            int curLen = words[i].length();
            int nextLen = words[i + 1].length();
            while(idx < curLen && idx < nextLen) {
                char& from = words[i][idx];
                char& to = words[i + 1][idx];

                if(from != to) {
                    if(graph[from - 'a'].count(to) == 0) {
                        in_degree[to - 'a']++;
                        graph[from - 'a'].insert(to);
                    }
                    break;
                }
                idx++;
            }
            if(idx == nextLen && curLen > nextLen) {
                cout << words[i] << " " << words[i + 1] << endl;
                return "";
            }
        }
        // 拓扑排序
        queue<char> q;
        string res = "";
        for(int i = 0; i < letters; i++) {
            if(seen_letters.count(i + 'a')) {
                if(in_degree[i] == 0) {
                    q.push(i + 'a');
                    res += i + 'a';
                }
            }else {
                in_degree[i] = -1;
            }
        }
        while(!q.empty()) {
            int len = q.size();
            while(len--) {
                char& from = q.front();
                q.pop();
                for(auto& to : graph[from - 'a']) {
                    if(in_degree[to - 'a'] == 1) {
                        q.push(to);
                        res += to;
                    }
                    in_degree[to - 'a']--;
                }
            }
        }
        // cout << res << endl;
        if(res.length() != seen_letters.size()) {
            return "";
        }
        return res;
    }
};

最后更新: July 23, 2022