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 words from the dictionary, where words 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: You may assume all letters are in lowercase. If the order is invalid, return an empty string. There may be multiple valid order of letters, return any one of them is fine.

分析:

  前后关系可看做是一种偏序关系,对于每个序列,可以看成是有向图,所有序列合在一起就成了一个大的有向图,本题可转换成有向图的拓扑排序,用BFS可解决。主要过程包含:1、根据string数组的信息映射成图;2、在图上计算出所有节点的入度;3、进行BFS,得到拓扑排序结果。故我用三个子函数来分别处理这三个过程。

代码:

//将string数组映射到图上,最坏时间复杂度就是每个字母遍历一遍,这也是必要,故也是最低时间复杂度
unordered_multimap<char, char> mapping(vector<string> &vs) {
//先处理第一列,用validcomp来记录哪些相邻行的值相等,用于后面的列的处理,不相等的就可以得偏序条件,用边来表示,存入edges中;然后处理第二列,以此类推。
unordered_multimap<char, char> edges;
unordered_set<int> validcomp, temp;
for(int i = ; i < vs.size(); i++)
validcomp.insert(i);
int j = ;
while(!validcomp.empty()) {
for(int pos : validcomp) {
if(vs[pos][j] != vs[pos - ][j])
edges.insert(make_pair(vs[pos - ][j], vs[pos][j]));
else
temp.insert(pos);
}
unordered_set<int> ().swap(validcomp);
validcomp.swap(temp);
j++;
}
return edges;
} //返回所有节点的入度,存入degree里
unordered_map<char, int> getDegree(unordered_multimap<char, char> &edges) {
unordered_map<char, int> degree;
for(char c = 'a'; c <= 'z'; c++) {
auto range = edges.equal_range(c);
auto pos = range.first;
while(pos != range.second) {
//指出节点未出现过,则设0,否则跳过;指入节点未出现过,则设1,否则++。
if(degree.find(pos->first) == degree.end())
degree[pos->first] = ;
if(degree.find(pos->second) != degree.end())
degree[pos->second]++;
else
degree[pos->second] = ;
pos++;
}
}
return degree;
} //进行BFS,用最朴素的方法,复杂度为O(N^2),用这个方法找到符合题目要求的顺序,如果能遍历完全所有节点,则return这个顺序;否则,return ""
bool bfs(string &str, unordered_map<char, int> degree, unordered_multimap<char, char> &edges) {
bool visited[];
memset(visited, , );
for(int i = ; i < degree.size(); i++) {
for(auto m : degree)
//入度为0则排入,然后更新入度hash表
if(!visited[int(m.first - 'a')] && m.second == ) {
visited[int(m.first - 'a')] = true;
str += m.first;
auto range = edges.equal_range(m.first);
auto pos = range.first;
while(pos != range.second) {
degree[pos->second]--;
pos++;
}
break;
}
}
//有环,则return ""
for(auto m : degree)
if(m.second != )
return false;
return true;
}
//主函数
string validOrder(vector<string> vs) {
//string数组映射到图edges上
unordered_multimap<char, char> edges = mapping(vs);
//返回所有节点的入度,存入degree;如果无效,则return "";
unordered_map<char, int> degree = getDegree(edges);
//进行BFS,找到合适的顺序,优先排入入度为0的点
string str = "";
bool valid = bfs(str, degree, edges);
return valid ? str : "";
}

其中,BFS过程,即函数bfs复杂度为O(N^2),N为节点个数,有改进的空间;可以优化为O(E),E为边的个数

//优化BFS
bool bfs(string &str, unordered_map<char, int> degree, unordered_multimap<char, char> &edges) {
queue<char> myq, temp;
for(auto m : degree)
if(m.second == )
myq.push(m.first);
while(!myq.empty()) {
while(!myq.empty()) {
char c = myq.front();
str += c;
myq.pop();
auto range = edges.equal_range(c);
auto pos = range.first;
while(pos != range.second) {
degree[pos->second]--;
if(degree[pos->second] == )
temp.push(pos->second);
pos++;
}
}
queue<char> ().swap(myq);
myq.swap(temp);
}
//有环,则return ""
for(auto m : degree)
if(m.second != )
return false;
return true;
}

最新文章

  1. java Web项目创建之一(普通java web项目的创建与发布)
  2. 从View向Controller传递复杂类型Json
  3. React Native知识2-Text组件
  4. Alpha阶段第一次Scrum Meeting
  5. Android Dex文件格式(二)
  6. hash_map的简洁实现
  7. Android 编译命令 make j8 2&gt;&amp;1 | tee build.log 解释
  8. 关于加了hibernate 框架的项目启动特别慢的问题
  9. scala言语基础学习十
  10. PHP底层的运行机制与原理
  11. SpringSide 3 中的多数据源配置的问题
  12. (转载)Mysql使用Describe命令判断字段是否存在
  13. ubuntu wine卸载程序并删除图标
  14. ThinkPHP框架二
  15. redis的分布式解决方式--codis
  16. on IRC, how to use secure connection(SSL) and get a cloak/vhost to hide your IP
  17. linux用户及权限管理
  18. JS中JSON对象的定义和取值
  19. 基于Python的Web应用开发实践总结
  20. 时间复杂度O(n),空间复杂度O(1)解斐波那契数列

热门文章

  1. VS2010在WIN7 64位系统下架设网站及路由器配置
  2. jq 图片裁剪
  3. node http.request请求
  4. java_设计模式_策略模式_Strategy pattern(2016-07-15)
  5. js转换/Date(........)/
  6. 【Linux】vi编辑器命令
  7. Swiper的简单实用方法
  8. Android SurfaceView使用
  9. IIC 概述之1
  10. SQL语句操作大全