269.Alien Dictionary
Tags: [topological_sort], [DFS], [lexicographical]
Com: {fb}
Link: https://leetcode.com/problems/alien-dictionary/#/description
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:
Given the following words in dictionary,
[
"wrt",
"wrf",
"er",
"ett",
"rftt"
]
The correct order is:"wertf"
.
Example 2:
Given the following words in dictionary,
[
"z",
"x"
]
The correct order is:"zx"
.
Example 3:
Given the following words in dictionary,
[
"z",
"x",
"z"
]
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.
Solution: Topological Sort
class Solution(object):
def alienOrder(self, words):
"""
:type words: List[str]
:rtype: str
"""
if not words:
return ''
graph = {}
for w in words:
for c in w:
if c not in graph:
graph[c] = set()
for i in xrange(len(words) - 1):
w1 = words[i]
w2 = words[i + 1]
for j in xrange(min(len(w1), len(w2))):
if w1[j] != w2[j]:
graph[w2[j]].add(w1[j])
break
result = self.topological_sort(graph)
return ''.join(result)
def topological_sort(self, graph):
if not graph:
return []
result = []
permanent_visited = set()
tmp_visited = set()
for v in graph:
if v in permanent_visited:
continue
try:
self.dfs(graph, v, result, permanent_visited, tmp_visited)
except ValueError, e:
return []
return result
def dfs(self, graph, v, result, permanent_visited, tmp_visited):
tmp_visited.add(v)
for child in graph[v]:
if child in permanent_visited:
continue
if child in tmp_visited:
raise ValueError('the input in invalid')
self.dfs(graph, child, result, permanent_visited, tmp_visited)
tmp_visited.remove(v)
permanent_visited.add(v)
result.append(v)
Revelation:
- Be attention to how do we draw the dependencies graph: First using all chars to initialize the graph, this is necessary, because there exists the case such as: words = ['wrf', 'wrfc']. Then each time compare two row words, scan these two words char by char until find the different char, once find the different char, stop.
Note:
- Time complexity = O(num of all chars).