BFS 解决拓扑排序
- 拓扑排序简介
- [3. ⽕星词典(hard)](#3. ⽕星词典(hard))
拓扑排序简介

3. ⽕星词典(hard)
- 题⽬链接:LCR 114. ⽕星词典
- 题⽬描述:
现有⼀种使⽤英语字⺟的外星⽂语⾔,这⻔语⾔的字⺟顺序与英语顺序不同。
给定⼀个字符串列表 words ,作为这⻔语⾔的词典, words 中的字符串已经 按这⻔新语⾔的字⺟顺序进⾏了排序 。
请你根据该词典还原出此语⾔中已知的字⺟顺序,并 按字⺟递增顺序 排列。若不存在合法字⺟顺序,返回 "" 。若存在多种可能的合法字⺟顺序,返回其中 任意⼀种 顺序即可。
字符串 s 字典顺序⼩于 字符串 t 有两种情况:
• 在第⼀个不同字⺟处,如果 s 中的字⺟在这⻔外星语⾔的字⺟顺序中位于 t 中字⺟之前,那么 s 的字典顺序⼩于 t 。
• 如果前⾯ min(s.length, t.length) 字⺟都相同,那么 s.length < t.length时, s 的字典顺序也⼩于 t 。
⽰例 1:
输⼊:words = ["wrt","wrf","er","ett","rftt"]
输出:"wertf"
⽰例 2:
输⼊:words = ["z","x"]
输出:"zx"
⽰例 3:
输⼊:words = ["z","x","z"]
输出:""
解释:不存在合法字⺟顺序,因此返回 "" 。
提⽰:
◦ 1 <= words.length <= 100
◦ 1 <= words[i].length <= 100
◦ words[i] 仅由⼩写英⽂字⺟组成 - 解法:

算法思路:
将题意搞清楚之后,这道题就变成了判断有向图时候有环,可以⽤拓扑排序解决。
如何搜集信息(如何建图):
a. 两层 for 循环枚举出所有的两个字符串的组合;
b. 然后利⽤指针,根据字典序规则找出信息。
算法代码:
java
class Solution
{
Map<Character, Set<Character>> edges = new HashMap<>(); // 邻接表
Map<Character, Integer> in = new HashMap<>(); // 统计每个节点的⼊度
boolean check;
public String alienOrder(String[] words)
{
// 1. 初始化⼊度哈希表 + 建图
for(String s : words)
{
for(int i = 0; i < s.length(); i++)
{
char ch = s.charAt(i);
in.put(ch, 0);
}
}
int n = words.length;
for(int i = 0; i < n; i++)
{
for(int j = i + 1; j < n; j++)
{
add(words[i], words[j]);
if(check == true) return "";
}
}
// 2. 拓扑排序
Queue<Character> q = new LinkedList<>();
for(char ch : in.keySet())
{
if(in.get(ch) == 0) q.add(ch);
}
StringBuffer ret = new StringBuffer();
while(!q.isEmpty())
{
char t = q.poll();
ret.append(t);
if(!edges.containsKey(t)) continue;
for(char ch : edges.get(t))
{
in.put(ch, in.get(ch) - 1);
if(in.get(ch) == 0) q.add(ch);
}
}
// 3. 判断
for(char ch : in.keySet())
{
if(in.get(ch) != 0) return "";
}
return ret.toString();
}
public void add(String s1, String s2)
{
int n = Math.min(s1.length(), s2.length());
int i = 0;
for( ; i < n; i++)
{
char c1 = s1.charAt(i), c2 = s2.charAt(i);
if(c1 != c2)
{
// c1 -> c2
if(!edges.containsKey(c1))
{
edges.put(c1, new HashSet<>());
}
if(!edges.get(c1).contains(c2))
{
edges.get(c1).add(c2);
in.put(c2, in.get(c2) + 1);
}
break;
}
}
if(i == s2.length() && i < s1.length()) check = true;
}
}