-
Notifications
You must be signed in to change notification settings - Fork 2
/
269. Alien Dictionary.py
100 lines (86 loc) · 2.83 KB
/
269. Alien Dictionary.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# 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.
# Example 1:
# Input:
# [
# "wrt",
# "wrf",
# "er",
# "ett",
# "rftt"
# ]
# Output: "wertf"
# Example 2:
# Input:
# [
# "z",
# "x"
# ]
# Output: "zx"
# Example 3:
# Input:
# [
# "z",
# "x",
# "z"
# ]
# Output: ""
# Explanation: The order is invalid, so return "".
# Note:
# You may assume all letters are in lowercase.
# You may assume that if a is a prefix of b, then a must appear before b in the given dictionary.
# If the order is invalid, return an empty string.
# There may be multiple valid order of letters, return any one of them is fine.
import collections
class Solution(object):
def alienOrder(self, words):
"""
:type words: List[str]
:rtype: str
"""
# https://www.youtube.com/watch?v=RIrTuf4DfPE
# 图的构建,拓扑遍历
degree = collections.defaultdict(int) # character and the in-degree
charGraph = collections.defaultdict(set) # a graph between the characters
# Step1 : Degree Map of each character.
for i in range(0, len(words)):
for char in words[i]:
degree[char] = 0
# Step2: Build graph using the sorted words array.
# If two chars are at the same position and different then char that appearsin word1 comes before char in word 2.
for i in range(0, len(words)-1): # Words are sorted lexicographically.
word1 = words[i]
word2 = words[i+1]
sm_word_len = min(len(word1), len(word2))
for j in range(0, sm_word_len):
c1 = word1[j]
c2 = word2[j]
if c1 != c2:
if c2 not in charGraph[c1]:
charGraph[c1].add(c2) # word
degree[c2] += 1
break
# Step 3: Perform Topological sort using Kahn's algorithm using Degree Map and Graph in Step 1 and 2.
queue = collections.deque([])
result = ""
for k, v in degree.items():
if not v:
queue.append(k)
# Kahn's algo.
# https://en.wikipedia.org/wiki/Topological_sorting
while queue:
node = queue.popleft()
result += node
for n in charGraph[node]:
degree[n] -= 1
# incase a disconnected graph.
if degree[n] == 0:
queue.append(n)
# Step 4: Check the result is Reasonable.
if len(result) == len(degree):
return result
else:
return ""