博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[LeetCode] Alien Dictionary
阅读量:4646 次
发布时间:2019-06-09

本文共 5607 字,大约阅读时间需要 18 分钟。

Problem Description:

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 words from the dictionary, wherewords are sorted lexicographically by the rules of this new language. Derive the order of letters in this language.

For example,

Given the following words in dictionary,

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

The correct order is: "wertf".

Note:

    1. You may assume all letters are in lowercase.
    2. If the order is invalid, return an empty string.
    3. There may be multiple valid order of letters, return any one of them is fine.

Well, this problem is not that easy. First you may need some clarifications about the problem itself. If you do, you may refer to  for a nice example which illustrates the purpose of this problem.

Moreover, you need to understand graph representation, graph traversal and specifically, topological sort, which are all needed to solve this problem cleanly.


DFS

Fortunately, jaewoo posts a nice solution in , whose code is rewritten as follows by decomposing the code into two parts:

  1. make_graph: Build the graph as a list of adjacency lists;
  2. toposort and acyclic: Traverse the graph in DFS manner to check for cycle and generate the topological sort.
1 class Solution { 2 public: 3     string alienOrder(vector
& words) { 4 if (words.size() == 1) return words[0]; 5 graph g = make_graph(words); 6 return toposort(g); 7 } 8 private: 9 typedef unordered_map
> graph;10 11 graph make_graph(vector
& words) {12 graph g;13 int n = words.size();14 for (int i = 1; i < n; i++) {15 bool found = false;16 string word1 = words[i - 1], word2 = words[i];17 int m = word1.length(), n = word2.length(), l = max(m, n);18 for (int j = 0; j < l; j++) {19 if (j < m && g.find(word1[j]) == g.end())20 g[word1[j]] = unordered_set
();21 if (j < n && g.find(word2[j]) == g.end())22 g[word2[j]] = unordered_set
();23 if (j < m && j < n && word1[j] != word2[j] && !found) {24 g[word1[j]].insert(word2[j]);25 found = true;26 }27 }28 }29 return g;30 }31 32 string toposort(graph& g) {33 vector
path(256, false), visited(256, false);34 string topo;35 for (auto adj : g)36 if (!acyclic(g, path, visited, topo, adj.first))37 return "";38 reverse(topo.begin(), topo.end());39 return topo;40 }41 42 bool acyclic(graph& g, vector
& path, vector
& visited, string& topo, char node) {43 if (path[node]) return false;44 if (visited[node]) return true;45 path[node] = visited[node] = true;46 for (auto neigh : g[node])47 if (!acyclic(g, path, visited, topo, neigh))48 return false;49 path[node] = false;50 topo += node;51 return true;52 }53 };

BFS

Well, given the graph well represented, the BFS solution is also not that hard :-)

1 class Solution { 2 public: 3     string alienOrder(vector
& words) { 4 if (words.size() == 1) return words[0]; 5 graph g = make_graph(words); 6 unordered_map
degrees = compute_indegree(g); 7 int numNodes = degrees.size(); 8 string order; 9 queue
toVisit;10 for (auto node : degrees)11 if (!node.second)12 toVisit.push(node.first);13 for (int i = 0; i < numNodes; i++) {14 if (toVisit.empty()) return "";15 char c = toVisit.front();16 toVisit.pop();17 order += c;18 for (char neigh : g[c])19 if (!--degrees[neigh])20 toVisit.push(neigh);21 }22 return order;23 }24 private:25 typedef unordered_map
> graph;26 27 graph make_graph(vector
& words) {28 graph g;29 int n = words.size();30 for (int i = 1; i < n; i++) {31 bool found = false;32 string word1 = words[i - 1], word2 = words[i];33 int l1 = word1.length(), l2 = word2.length(), l = max(l1, l2);34 for (int j = 0; j < l; j++) {35 if (j < l1 && g.find(word1[j]) == g.end())36 g[word1[j]] = unordered_set
();37 if (j < l2 && g.find(word2[j]) == g.end())38 g[word2[j]] = unordered_set
();39 if (j < l1 && j < l2 && word1[j] != word2[j] && !found) {40 g[word1[j]].insert(word2[j]);41 found = true;42 }43 }44 }45 return g; 46 }47 48 unordered_map
compute_indegree(graph& g) {49 unordered_map
degrees;50 for (auto adj : g) {51 if (!degrees[adj.first]);52 for (char neigh : adj.second)53 degrees[neigh]++;54 }55 return degrees;56 }57 };

BTW, if (!degrees[adj.first]); in compute_indegree is to make sure that a node with 0indegree will not be left out. For this part, something about the default constructor ofunordered_map is useful: each time when we try to access a key k which is still not inunordered_map by [k], the default constructor of unordered_map will set its value to 0.


Well, this problem is not easy and the code is also long. If you have difficulties understanding it,  you may review the fundamentals of graph (Introduction to Algorithms is a good reference) and try to solve older LeetCode problems like , and first.

转载于:https://www.cnblogs.com/jcliBlogger/p/4758761.html

你可能感兴趣的文章
软工网络15团队作业2——团队计划
查看>>
Android屏幕适配
查看>>
ps简单操作文档
查看>>
CSS之float样式
查看>>
08test
查看>>
测试用例方法总结
查看>>
基数---SQL Server 2008 Bible
查看>>
第一个JSP程序
查看>>
数组常用的API——splice()截取
查看>>
sbt教程
查看>>
djang1.7 复制粘贴小项目(generic View的使用)
查看>>
Python For Delphi---更好地协同(续)
查看>>
Java的内存泄漏
查看>>
152-PHP htmlspecialchars函数
查看>>
061-PHP函数定义默认参数
查看>>
Genymotion下载模拟器失败解决方案
查看>>
The Apostrophe and the Quote Function ‘和引用函数 未翻译完)
查看>>
win8开发入门——国际化(多语言支持)
查看>>
科学计算三维可视化---Mayavi入门(Mayavi库的基本元素和绘图实例)
查看>>
python学习笔记-问题
查看>>