269. 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, 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:
- 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.
链接: http://leetcode.com/problems/alien-dictionary/
题解:
这道题也是卡了很久,原因在于题意理解不明确。方法还是Topological Sorting,这题的意思是 - Words are sorted, 跟每个Word里面的letter顺序并没有什么关系。就比如"apple"排在"banana"前面,但并不是"apple"里面的"a"就排在"p"前面。所以之前花了不少时间根据每个单词内部的顺序构造edges,结果都是错的。 这种东西归根结底还是我自己的英语不好。写了一大堆总是通不过,发现题目真正含义以后就好很多了,以后面试的话也要多交流多沟通,免得题意弄不清楚白浪费时间做题。另外,对于图来说,图的三种表达方式, list of edges, ajacency matrix和ajacency lists一定要搞清楚,多弄明白。
Kahn's Algorithm: 先把输入words转化为Adjacency Lists或者list of edges,然后使用Course Schedule II的方法进行Topological Sorting。这里我们使用Kahn's Algorithm,先计算inDegree,然后维护一个Queue来进行BFS。
Time Complexity - O(VE),Space Complexity - O(VE)
public class Solution {
public String alienOrder(String[] words) { // Topological sorting - Kahn's Algorithm
if(words == null || words.length == 0) {
return "";
}
Map<Character, HashSet<Character>> map = new HashMap<>();
Map<Character, Integer> inDegree = new HashMap<>();
for(String s : words) {
for(int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
inDegree.put(c, 0);
}
}
for(int i = 1; i < words.length; i++) { // find (prevChar, curChar) pairs as edges
String prevStr = words[i - 1];
String curStr = words[i];
int len = Math.min(prevStr.length(), curStr.length());
for(int j = 0; j < len; j++) {
char curChar = curStr.charAt(j);
char prevChar = prevStr.charAt(j);
if(curChar == prevChar) {
continue;
} else { // find edges;
if(map.containsKey(prevChar)) {
if(!map.get(prevChar).contains(curChar)) {
map.get(prevChar).add(curChar);
inDegree.put(curChar, inDegree.get(curChar) + 1);
}
} else {
HashSet<Character> tmpSet = new HashSet<>();
tmpSet.add(curChar);
map.put(prevChar, tmpSet);
inDegree.put(curChar, inDegree.get(curChar) + 1);
}
break;
}
}
}
Queue<Character> queue = new LinkedList<>();
for(char c : inDegree.keySet()) {
if(inDegree.get(c) == 0) {
queue.offer(c);
}
}
StringBuilder res = new StringBuilder();
while(!queue.isEmpty()) {
char c = queue.poll();
res.append(c);
if(map.containsKey(c)) {
for(char l : map.get(c)) {
inDegree.put(l, inDegree.get(l) - 1);
if(inDegree.get(l) == 0) {
queue.offer(l);
}
}
}
}
if(res.length() != inDegree.size()) {
return "";
}
return res.toString();
}
}
题外话:
这几天食物过于丰富。周五BCD豆腐,周六刘一手火锅(改名了),周日又去了法拉盛吃老周全羊馆,结果就懈怠了。不过和小伙伴们玩玩三国杀放松一下也是很好的。房子的装修也接近尾声,明天周一估计就可以收工了,希望一切顺利。 同时,明天也开始为期一周的培训,主要是Modern Web Development,讲JavaScript的。同时Coursera也有一门讲AngularJS的课程,香港科技大学开设的,明天开始第一天。要趁这个机会好好学一些AngularJS。
二刷:
简化了一下。思路不那么乱了。有几个特殊的点要注意:
- 输入中只含有26个小写字母,所以我们可以可以用一个int[26]来计算inDegree
- 输出的时候只输出在words里出现过的字符,所以先把字符保存在一个set里。 其实这里也可以和map一起遍历,但需要不少额外的边界条件
- 注意单词内部的顺序没有关系,只有单词和前一个单词相同位置不同字间才有先后顺序。
- 要注意图的adjancency lists表示结构, 使用Map<Character, Set<Character>>可能会比 Map<Character, List<Character>>快。同时要注意这道题里key保存的是先输出的字符,value里面保存的是后输出的字符。inDegree里也是后输出字符的value被增加
- 结尾的时候假如sb.length() < set.size(),说明无法组成一个topological order,我们返回"",否则返回一个topological sorted string sb.toString();
Java:
public class Solution {
public String alienOrder(String[] words) { // Topological sorting - Kahn's Algorithm
if(words == null || words.length == 0) {
return "";
}
Map<Character, Set<Character>> graph = new HashMap<>();
Set<Character> set = new HashSet<>();
for (String word : words) {
for (int i = 0; i < word.length(); i++) {
set.add(word.charAt(i));
}
}
int[] inDegree = new int[26];
for (int k = 1; k < words.length; k++) {
String preStr = words[k - 1];
String curStr = words[k];
for (int i = 0; i < Math.min(preStr.length(), curStr.length()); i++) {
char preChar = preStr.charAt(i);
char curChar = curStr.charAt(i);
if (preChar != curChar) {
if (!graph.containsKey(preChar)) {
graph.put(preChar, new HashSet<Character>());
}
if (!graph.get(preChar).contains(curChar)) {
inDegree[curChar - 'a']++;
}
graph.get(preChar).add(curChar);
break;
}
}
}
Queue<Character> queue = new LinkedList<>();
for (int i = 0; i < inDegree.length; i++) {
if (inDegree[i] == 0) {
char c = (char)('a' + i);
if (set.contains(c)) {
queue.offer(c);
}
}
}
StringBuilder sb = new StringBuilder();
while (!queue.isEmpty()) {
char c = queue.poll();
sb.append(c);
if (graph.containsKey(c)) {
for (char l : graph.get(c)) {
inDegree[l - 'a']--;
if (inDegree[l - 'a'] == 0) {
queue.offer(l);
}
}
}
}
return sb.length() != set.size() ? "" : sb.toString();
}
}
Reference:
https://leetcode.com/discuss/53997/the-description-is-wrong
https://leetcode.com/discuss/71991/8ms-clean-java-using-topological-sort-and-dfs
https://leetcode.com/discuss/65274/java-solution-basic-topological-sort
https://leetcode.com/discuss/69894/fastest-java-solution-topological-comments-improvements
https://leetcode.com/discuss/54002/simple-idea-based-on-dfs-4ms-in-c
https://leetcode.com/discuss/54549/java-toposort-solution-clean
https://leetcode.com/discuss/54188/16-18-lines-python-29-lines-c
269. Alien Dictionary的更多相关文章
- [LeetCode] 269. Alien Dictionary 另类字典
There is a new alien language which uses the latin alphabet. However, the order among letters are un ...
- 269. Alien Dictionary 另类字典 *HARD*
There is a new alien language which uses the latin alphabet. However, the order among letters are un ...
- [leetcode]269. Alien Dictionary外星字典
There is a new alien language which uses the latin alphabet. However, the order among letters are un ...
- 269. Alien Dictionary火星语字典(拓扑排序)
[抄题]: There is a new alien language which uses the latin alphabet. However, the order among letters ...
- [LeetCode] 269. Alien Dictionary 外文字典
There is a new alien language which uses the latin alphabet. However, the order among letters are un ...
- LeetCode 269. Alien Dictionary
原题链接在这里:https://leetcode.com/problems/alien-dictionary/ 题目: There is a new alien language which uses ...
- [Locked] Alien Dictionary
Alien Dictionary There is a new alien language which uses the latin alphabet. However, the order amo ...
- 【Leetcode_easy】953. Verifying an Alien Dictionary
problem 953. Verifying an Alien Dictionary solution: class Solution { public: bool isAlienSorted(vec ...
- Verifying an Alien Dictionary
2019-11-24 22:11:30 953. Verifying an Alien Dictionary 问题描述: 问题求解: 这种问题有一种解法是建立新的排序和abc排序的映射,将这里的str ...
随机推荐
- 简单的C语言小学四则运算设计
题目:设计一个简单的四则运算编辑器 思路:我使用的是C语言编程,看到题目首先要随机出3个随机数,其中两个为100以内的随机数(a,b),一个为0~3的随机数(k). k值的变化使得+ - * /的变化 ...
- mongodb修改器
mongodb修改器 转载自:http://blog.csdn.net/mcpang/article/details/7752736 mongodb修改器(\(inc/\)set/\(unset/\) ...
- Hibernate 检索查询的几种方式(HQL,QBC,本地SQL,集成Spring等)
1.非集成Spring hibernate的检索方式,主要有以下五种. 1.导航对象图检索方式.(根据已经加载的对象,导航到其他对象.) 2.OID检索方式.(按照对象的OID来检索对象.) 3.HQ ...
- c语言学习strcopy
自己写了一个字符串复制函数: #include<stdio.h> #include<assert.h> char *mystrcpy(char *des,char *ser) ...
- bzoj 1565 最大权闭合子图
因为每个植物都有保护的点(每排相邻的右面的算是保护左面的),所以连他和保护 的点一条边,然后每个点有自己的权值,要找到最大的权值且满足每个点在访问时他 的前驱一定被访问,那么反向建边,转化为后继必须访 ...
- BZOJ 1012: [JSOI2008]最大数maxnumber 线段树
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1012 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作.语法:Q L 功能: ...
- GS线程
void GameServer::ProcessThread() { try {//在ui线程里面搞个大try不是说try效率不好吗,难道只是为了出现错误发现在GS线程里面出现的吗 ProcessTh ...
- 转 Eclipse下svn的创建分支/合并/切换使用
最近接项目要求,要在svn主干上创建分支,用分支来进行程序的bug修改,而主干上进行新功能的开发.分支上的bug修改完,发布后,可以合并到主干上.项目程序可以在主干和分支之间进行切换,来实现主干和分支 ...
- JQuery表单验证插件EasyValidator,超级简单易用!
本插件的宗旨是:用户无需写一行JS验证代码,只需在要验证的表单中加入相应的验证属性即可,让验证功能易维护,可扩展,更容易上手. DEMO中已经包含了常用的正则表达式,可以直接复用,为了考虑扩展性,所以 ...
- CSS预处理器实践之Sass、Less大比拼[转]
什么是CSS预处理器? CSS可以让你做很多事情,但它毕竟是给浏览器认的东西,对开发者来说,Css缺乏很多特性,例如变量.常量以及一些编程语法,代码难易组织和维护.这时Css预处理器就应运而生了.Cs ...