LintCode 892: Alien Dictionary (topological sorting题)

  1. Alien Dictionary

There is a new alien language which uses the latin alphabet. However, the order among letters are unknown to you. You receive a list of non-empty words from the dictionary, where words are sorted lexicographically by the rules of this new language. Derive the order of letters in this language.

Example
Example 1:

Input:[“wrt”,“wrf”,“er”,“ett”,“rftt”]
Output:“wertf”
Explanation:
from “wrt"and"wrf” ,we can get ‘t’<‘f’
from “wrt"and"er” ,we can get ‘w’<‘e’
from “er"and"ett” ,we can get ‘r’<‘t’
from “ett"and"rftt” ,we can get ‘e’<‘r’
So return “wertf”

Example 2:

Input:[“z”,“x”]
Output:“zx”
Explanation:
from “z” and “x”,we can get ‘z’ < ‘x’
So return “zx”
Notice
You may assume all letters are in lowercase.
The dictionary is invalid, if a is prefix of b and b is appear before a.
If the order is invalid, return an empty string.
There may be multiple valid order of letters, return the smallest in normal lexicographical order

解法1:
topologial sorting.
注意:

  1. 要用priority queue,因为结果有顺序。而且要用minHeap!
  2. 建图时把word[i]和word[i+1]比较,从头开始比,碰到第一个不同的字符就返回。
class Solution {
public:
    /**
     * @param words: a list of words
     * @return: a string which is correct order
     */
    string alienOrder(vector<string> &words) {
        map<char, set<char>> graph = buildGraph(words);
        return topologicalSorting(graph);
    }
    
private:
    map<char, set<char>> buildGraph(vector<string> &words) {
        map<char, set<char>> graph;
        
        //put all the chars in graph, the set is empty at this time
        for (int i = 0; i < words.size(); ++i) {
            for (int j = 0; j < words[i].size(); ++j) {
                if (graph.find(words[i][j]) == graph.end())
                    graph[words[i][j]] = {};
            }
        }

        for (int i = 0; i < words.size() - 1; ++i) {
            int len = min(words[i].size(), words[i + 1].size());
            for (int j = 0; j < len; ++j) {
                if (words[i][j] != words[i + 1][j]) {
                    graph[words[i][j]].insert(words[i + 1][j]);
                    break;
                }
            }
        }
        return graph;
    }
    
    map<char, int> getIndegree(map<char, set<char>> graph) {
        map<char, int> indegree;
        for (auto elem : graph) {
            indegree[elem.first] = 0;
        }
        for (auto elem: graph) {
            for (auto c : elem.second) {
                indegree[c]++;
            }
        }
        return indegree;
    }
    
    string topologicalSorting(map<char, set<char>> graph) {
        map<char, int> indegree = getIndegree(graph);
        priority_queue<char, vector<char>, greater<char>> pq;   //minHeap
        string str;
        for (auto elem : indegree) {
            if (indegree[elem.first] == 0) {
                pq.push(elem.first);
            }
        }
        
        while(!pq.empty()) {
            char topChar = pq.top();
            pq.pop();
            str += topChar;
            for (char neighbor : graph[topChar]) {
                indegree[neighbor]--;
                if (indegree[neighbor] == 0) {
                    pq.push(neighbor);
                }
            }
        }

        if (str.size() != indegree.size()) return "";
        return str;
    }
};

二刷:跟上面的方法类似。注意:

  1. 最后要检查res.size() == inDegrees.size()。这里是为了防止有环,有环的话只会输出环外的元素。当然有环的话也不能用topological sorting。
  2. inDegrees[l.second]++ 必须在i循环外进行,不然的话,同样的链接比如说(a,b)可能会出现多次,而b的indegree会每次都错误累加。但实际上只要加1次就可以了。
class Solution {
public:
    string alienOrder(vector<string>& words) {
        set<pair<char, char>> linkSets;
        unordered_map<char, int> inDegrees;
        priority_queue<char, vector<char>, greater<char>> minHeap;
        string res;
        
        //initialization
        for (auto word : words) {
            for (auto c : word) {
                inDegrees[c] = 0;
            }
        }
       
        //construct linkSets
        int j = 0;
        for (int i = 0; i < (int)words.size() - 1; i++) {
            int minLen = min(words[i].size(), words[i + 1].size());
            for (j = 0; j < minLen; j++) {
                if (words[i][j] != words[i + 1][j]) {
                    linkSets.insert({words[i][j], words[i + 1][j]});
                    //inDegrees[words[i + 1][j]]++; //注意要放到循环外面,因为如果有两个同样的连接(a,b),这里会把b的indegree加到2,但实际上只有1.
                    break;
                }
            }
            if (j == minLen && words[i].size() > words[i + 1].size()) return "";
        }
        for (auto l : linkSets) {
            inDegrees[l.second]++;
        }

        //topological sorting
        for (auto in : inDegrees) {
            if (in.second == 0) {
                minHeap.push(in.first);
            }
        }
        while (!minHeap.empty()) {
            char topChar = minHeap.top();
            minHeap.pop();
            res += topChar;
            for (auto link : linkSets) {
                if (topChar == link.first) {
                    inDegrees[link.second]--;
                    if (inDegrees[link.second] == 0) {
                        minHeap.push(link.second);
                    }
                }
            }
        }
        return res.size() == inDegrees.size() ? res : ""; //防止有环,有环的话只会输出环外的元素
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值