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 non-empty words from the dictionary, where words are sorted lexicographically by the rules of this new language. Derive the order of letters in this language.
题目理解:1.单词内部字母没有排序规律。wrt不代表w->r->t。2.在前面字母相同的情乱下(没有也算是相同),比较相同位置的字母,单词依据该位置的字母排序。
思路:参考普通的英文词典,普通的词典是按照字母表的顺序给单词排序,这道题是通过单词排序找到它排序的规则。
字母代表结点,优先级高的字母指向优先低的字母,这就组成了DAG图。这样就可以用拓扑排序,找到这个词典的排序规则。
问题变成:构建一个DAG图+在图上拓扑排序
代码:只在本地测试了一下,等有钱开了会员去LeetCode上跑一下。
def alienOrder(words):
if len(words)==0:
return ""
indegree = {}
hash = {}
# 声明记录入度的哈希表,并初始化
for word in words:
for i in word:
indegree[i] = 0
hash[i] = []
# 构建DAG图
for i in range(len(words)-1):
k=0
while ((k<min(len(words[i]),len(words[i+1]))) and words[i][k]==words[i+1][k]):
k+=1
if (k>=min(len(words[i]),len(words[i+1]))):
continue
indegree[words[i+1][k]]+=1
hash[words[i][k]].append(words[i+1][k])
res = []
# 拓扑排序
while indegree:
# Q为空,也就是图不是DAG,终止
try:
Q = list(indegree.keys())[list(indegree.values()).index(0)]
except:
return ""
# 遍历左右的当前入度为0的字母
for i in Q:
# 把它所有指向的字母入度-1
for j in hash[i]:
indegree[j] -= 1
# 记录入度的表中弹出入度为0的(老的字母,通过入度-1生成的新入度为0的字母这轮不弹出)
indegree.pop(i)
# 邻接表中弹出同样弹出
hash.pop(i)
# 添加到结果里
res.append(i)
return res
我一开始思路卡在了DAG图的建立上了,想上来就把第一位的所有字母排好序。
不管是什么时候遇到困难的编程问题,问一问自己:“如何用图来表述这个问题?”。图都是用于表示数据之间的关系。 诀窍在于如何定义“关系”。
后来收到启发,其实一次只需要按顺序依次拿出相邻的两个单词找出一对字母的排序就可以。换句话说知道4>3,3>2,2>1,和知道4>3>2>1是一样的。example1中,通过这种方法只能知道w->e,如果从全部单词考虑可以知道w->e->r。不过后面还能知道e->r,所以r肯定在e的后面,又因为e在w的后面,所以r肯定在w的后面,这种方法不会丢失信息。就是建立更加简洁的DAG图了。