1. 程式人生 > >Leetcode 269. Alien Dictionary

Leetcode 269. Alien Dictionary

Problem:

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 1:

Input:
[
  "wrt",
  "wrf",
  "er",
  "ett",
  "rftt"
]

Output: "wertf"

Example 2:

Input:
[
  "z",
  "x"
]

Output: "zx"

Example 3:

Input:
[
  "z",
  "x",
  "z"
] 

Output: "" 

Explanation: The order is invalid, so return "".

Note:

  1. You may assume all letters are in lowercase.
  2. You may assume that if a is a prefix of b, then a must appear before b in the given dictionary.
  3. If the order is invalid, return an empty string.
  4. There may be multiple valid order of letters, return any one of them is fine.

Solution:

這道題可以分為兩部分。

1. 根據單詞之間的關係構建拓撲圖

  以第一個例子為例,對每對相鄰的兩個字串提取拓撲關係,如“wrt"和"wrf",找到兩個字串第一個不相同的字元,將t->f插入雜湊表,以此類推。注意如果第一個字串是第二個字串新增字尾組成的話,則可以直接返回空,如”wrt“和”wr“,因為它不存在拓撲排序的可能性。

2. 利用BFS得到結果

  這一步是演算法核心,難點在於我們不知道哪個字元才是起始點。所以先用一個indegree陣列計算每個出現過的字元的入度,如果為0則可以斷定它必為起始點,則將它插入佇列中,注意可能存在多個起始點。然後利用BFS和第一步得到的拓撲關係,每推出一個字元就將這個字元的所有出度推入佇列,如果發現推入的字元已經訪問過,則必然存在環,輸出空。注意可能存在這種情況,a->b,c->b,如果簡單的將出度推入佇列則b會推入兩次,所以我們只有在indegree['b']為0時才推入佇列,否則自減1。

Code:

 1 class Solution {
 2 public:
 3     string alienOrder(vector<string>& words) {
 4         if(words.size() == 0) return "";
 5         if(words.size() == 1) return words[0];
 6         unordered_map<char,vector<char>> graph;
 7         vector<bool> allchar(128,false);
 8         for(int i = 1;i != words.size();++i){
 9             string str1 = words[i-1];
10             string str2 = words[i];
11             int p1 = 0;
12             int p2 = 0;
13             for(char c:str1) allchar[c] = true;
14             for(char c:str2) allchar[c] = true;
15             while(p1 != str1.size() && p2 != str2.size() && str1[p1] == str2[p2]){
16                 p1++;
17                 p2++;
18             }
19             if(p1 != str1.size() && p2 != str2.size())
20                 graph[str1[p1]].push_back(str2[p2]);
21             else{
22                 if(p2 == str2.size() && str1.size() > str2.size())
23                     return "";
24             }
25         }
26         
27         vector<int> indegree(128,0);
28         for(auto iter:graph){
29             vector<char> v = iter.second;
30             for(char c:v)
31                 indegree[c]++;
32         }
33         
34         string result = "";
35         queue<char> q;
36         vector<bool> visited(128,false);
37         for(int i = 0;i != 128;++i){
38             if(allchar[i] && indegree[i] == 0){
39                 q.push(i);
40             }
41         }
42         while(!q.empty()){
43             char front = q.front();
44             q.pop();
45             result = result+front;
46             visited[front] = true;
47             if(graph.find(front) != graph.end()){
48                 for(int i = 0;i != graph[front].size();++i){
49                     if(visited[graph[front][i]]) return "";
50                     indegree[graph[front][i]]--;
51                     if(indegree[graph[front][i]] == 0)
52                         q.push(graph[front][i]);
53                 }
54             }
55         }
56         for(int i = 0;i != 128;++i){
57             if(indegree[i] != 0)
58                 return "";
59         }
60         return result;
61     }
62 };