题目链接
思路- 这种题目难点就两个 抽象为图并构建邻接表、拓扑排序
- 首先我们可以确定的是所有出现的字符是图中的结点,如果某个字符ch1优先级大于ch2,那么就应该存在一条ch1指向ch2的弧
- 我们可以根据words数组中的顺序找到单词的优先级关系,因为单词是字典序,所以只需要找到前后两个字母第一个不一样的字符 那么必然有前面的字符优先级高于后面的字符。但是有两种特殊情况,如果前面是后面的子串,那么自然找不到不一样的字符,如果后面是前面的子串,那么排序是错误的。
- 需要注意的是 某个单词如gril,字符之间并不存在优先级
- 还有就是在创建图的过程中还需要检查是否合法,比如如果存在一条ch1指向ch2的边,那么自然不能有ch2指向ch1的边
class Solution {
public String alienOrder(String[] words) {
Map<Character,Set<Character>> graph = new HashMap<>();
Map<Character,Integer> inDegrees = new HashMap<>();
// 创建节点信息
for(String word : words){
for(char ch : word.toCharArray()){
graph.putIfAbsent(ch,new HashSet<>());
inDegrees.putIfAbsent(ch,0);
}
}
// 根据外部顺序构建图
for(int i = 0 ; i < words.length ; i++){
for(int j = i + 1 ; j < words.length ; j++){
String str1 = words[i] , str2 = words[j];
// 找到二者第一个不同的字符的索引
int index = 0;
while(index < str1.length() && index < str2.length() && str1.charAt(index) == str2.charAt(index))
index++;
// 如果str1是str2的子串
if(index == str1.length())
continue;
if(index == str2.length())
return "";
// 如果不是 就找到第一个不同的字符 然后补充图的内容
char ch1 = str1.charAt(index) , ch2 = str2.charAt(index);
if(graph.get(ch2).contains(ch1))
return "";
if(!graph.get(ch1).contains(ch2)){
graph.get(ch1).add(ch2);
inDegrees.put(ch2,inDegrees.get(ch2)+1);
}
}
}
// 拓扑排序
Queue<Character> queue = new LinkedList<>();
StringBuilder sb = new StringBuilder();
for(Map.Entry<Character,Integer> entry : inDegrees.entrySet()){
if(0 == entry.getValue())
queue.offer(entry.getKey());
}
while(0 != queue.size()){
char ch = queue.poll();
sb.append(ch);
for(char ch2 : graph.get(ch)){
inDegrees.put(ch2,inDegrees.get(ch2)-1);
if(0 == inDegrees.get(ch2))
queue.offer(ch2);
}
}
return sb.toString();
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)