1.题目描述
现有一种使用字母的全新语言,这门语言的字母顺序与英语顺序不同。
假设,您并不知道其中字母之间的先后顺序。但是,会收到词典中获得一个 不为空的 单词列表。因为是从词典中获得的,所以该单词列表内的单词已经 按这门新语言的字母顺序进行了排序。
您需要根据这个输入的列表,还原出此语言中已知的字母顺序。
示例 1:
输入:
[
"wrt",
"wrf",
"er",
"ett",
"rftt"
]输出: "wertf"
示例 2:输入:
[
"z",
"x"
]输出: "zx"
示例 3:输入:
[
"z",
"x",
"z"
]输出: ""
解释: 此顺序是非法的,因此返回 ""。
注意:你可以默认输入的全部都是小写字母
假如,a 的字母排列顺序优先于 b,那么在给定的词典当中 a 定先出现在 b 前面
若给定的顺序是不合法的,则返回空字符串即可
若存在多种可能的合法字母顺序,请返回其中任意一种顺序即可
2.解题思路
- 构造图:在构建图是,比较相邻两个words,逐个比较两个words相同位置的字符,直到找到第一个字符不相同的位置,这个位置的两个字符我们可以获得有效信息,也就是这两个字符在alien order中的相对顺序。需要注意的是也就是这个位置有用,因为后面的不同位置我们无法获取任何信息。
- 拓扑排序算法(bfs)
- 生成结果,判断是否有环
3.代码实现
class Solution(object):
def alienOrder(self, words):
"""
:type words: List[str]
:rtype: str
"""
# 1.构建图
hashMap = {}
for i in range(len(words)-1):
for j in range(min(len(words[i]), len(words[i+1]))):
# 如果字符相同,比较下一个
if words[i][j] == words[i+1][j]:
continue
# 保存第一个不同的字符顺序,位于前面的字母作为key,位于后面的字母存到set中作为值
else:
s=hashMap.get(words[i][j],set())
s.add(words[i+1][j])
hashMap[words[i][j]] = s
break
degrees = [-1 for _ in range(26)]
# 将出现过的字符的入度设定为0,为了统计所有出现的不同的字母的个数
# 没有出现的字母入度为-1,出现了的字母的入度为非负数
for word in words:
for c in word:
degrees[ord(c)-ord("a")] = 0
for key,value in hashMap.items():
for val in value:
# 出现了的字母的入度+1
degrees[ord(val)-ord("a")] += 1
# 创建一个Queue保存入度为0的节点
Q = []
total = 0
for i in range(26):
if degrees[i] != -1:
total+=1
if degrees[i] == 0:
Q.append(chr(i+ord("a")))
res = ""
while Q:
t = Q.pop(0)
res+=t
# 图中的最后一个字母,在本例中例如f是不在hashmap中的
if t in hashMap:
for c in hashMap[t]:
# 将邻接点入度-1
degrees[ord(c)-ord("a")] -= 1
if degrees[ord(c)-ord("a")] == 0:
Q.append(c)
# 判断是否有环
if len(res) != total:
return ""
else:
return res