刷
June-27-2019
比较难= = 用indegree的思路来做的,或者说拓扑的思路topological sort
prevStr和tempStr,说明prevStr里的char在tempStr里的char之前.
eg: abc&abd => d -> c 说明D前面有一个C
要给所有出现的char建SET,记录前面有哪些char。 SET的大小代表char的indegree是几(前面有几个CHAR)
上面的例子就这样 =>
d : {c}
遍历所有STR来比较,然后从indegree=0的开始删,和course schedule一个做法
有问题的话会出现a的 set里有B, B的SET里有A,相互矛盾。
有个隐藏条件
"abc"
"ab"
是错的,空的永远排在任何字母之前,不容易想到,不用过分纠结这个。
Time Complexity主要耗在遍历上 O(mn)
public String alienOrder(String[] words) {
Map<Character, Set<Character>> parentMap = new HashMap<>();
for (String s : words) {
for (char c : s.toCharArray()) {
if (!parentMap.containsKey(c)) {
parentMap.put(c, new HashSet<>());
}
}
}
for (int i = 1; i < words.length; i ++) {
String prevStr = words[i - 1];
String tempStr = words[i];
int len = Math.min(prevStr.length(), tempStr.length());
for (int j = 0; j < len; j ++) {
char prevChar = prevStr.charAt(j);
char tempChar = tempStr.charAt(j);
if (prevChar != tempChar) {
if (!parentMap.get(tempChar).contains(prevChar)) {
parentMap.get(tempChar).add(prevChar);
}
break;
}
if (j == prevStr.length() - 1 && len + 1 == prevStr.length()) return "";
}
}
ArrayDeque<Character> q = new ArrayDeque<>();
for (Map.Entry<Character, Set<Character>> entry : parentMap.entrySet()) {
if (entry.getValue().isEmpty()) {
q.offerLast(entry.getKey());
}
}
StringBuilder sb = new StringBuilder();
while (!q.isEmpty()) {
char tempChar = q.pollFirst();
parentMap.remove(tempChar);
sb.append(tempChar);
for (Map.Entry<Character, Set<Character>> entry : parentMap.entrySet()) {
if (entry.getValue().contains(tempChar)) {
entry.getValue().remove(tempChar);
if (entry.getValue().isEmpty()) {
q.offerLast(entry.getKey());
}
}
}
}
if (parentMap.isEmpty()) {
return sb.toString();
} else {
return "";
}
}
=====================
一刷。
直接看的解法,大多数是用拓扑排序做的。
说实话挺难的,直接看别人的CODE才理解。
一开始也理解错了,单词里面的letter是没有顺序的,只是dictionary是按特殊顺序排列的。但是又不能只比较首字母,因为有可能首字母相同。
Time: 假如26个字母。 不是很好算。。
建图最差是N*N,但是这种情况发生时,整个图都是V,没有E。 就不用后面的拓扑排序了。拓扑排序是有边,才可以。。
O(26²) + O(26) + O(26) * O(E) 大概这么个意思
第一个26平方是建图,然后O(26)是入queue, O(26) * O(E)是拓扑排序。。
这个题还有别的坑。
"abc"
"abcd"
这样是没事的
"abcd"
"abc"
这样是错的,‘ ’在‘d'之前是错的。
有个rule没说,' ' shall before any letters,但是大家基本都以为Alien rule can be any rules it defines..= =
public class Solution {
public String alienOrder(String[] words) {
if (words.length == 0) return "";
Set<Character> letterSet = new HashSet<>();
int[] inDegree = new int[26];
Map<Character, HashSet<Character>> order = new HashMap<>();
for (String s : words) {
for (char c : s.toCharArray()) {
letterSet.add(c);
}
}
for (int i = 1; i < words.length; i++) {
String prevStr = words[i-1];
String tempStr = words[i];
if (prevStr.equals(tempStr)) continue;
int len = Math.min(prevStr.length(), tempStr.length());
for (int j = 0; j < len; j++) {
char prevC = prevStr.charAt(j);
char tempC = tempStr.charAt(j);
if (prevC != tempC) {
if (!order.containsKey(prevC)) {
order.put(prevC, new HashSet<>());
}
if (!order.get(prevC).contains(tempC)) {
order.get(prevC).add(tempC);
inDegree[tempC - 'a'] ++;
}
break;
}
if (j == len - 1 && prevStr.length() > tempStr.length()) return "";
}
}
Queue<Character> q = new LinkedList<>();
for (int i = 0; i < inDegree.length; i++) {
if (inDegree[i] == 0 && letterSet.contains((char)('a' + i))) {
q.offer((char)('a' + i));
}
}
StringBuilder sb = new StringBuilder();
while (!q.isEmpty()) {
char tempChar = q.poll();
sb.append(tempChar);
if (order.containsKey(tempChar)) {
for (char c : order.get(tempChar)) {
inDegree[c - 'a'] --;
if (inDegree[c - 'a'] == 0) {
q.offer(c);
}
}
}
}
if (sb.length() != letterSet.size()) {
return "";
} else {
return sb.toString();
}
}
}