alien_dictionary
1from collections import Counter, defaultdict, deque 2 3 4# @leet start 5class Solution: 6 def alienOrder(self, words: list[str]) -> str: 7 """ 8 This question asks us to return an ordering of characters given a set 9 of sorted words. 10 11 First, we describe the relation between the characters. We do this by 12 extracting the first character of each pair that doesn't match, and 13 noting that the left side char comes before the right side. 14 15 For these words: 16 17 wrt 18 wrf 19 er 20 ett 21 rftt 22 23 the pairs would be (wrt, wrf), (wrf, er), (er, ett), (ett, rftt). 24 25 For each pair, we want to find which ones come before, so: 26 27 (wrt, wrf) = t -> f (since wr are the same, t and f are the first differing 28 characters, and t is on the left side of our pair, so t comes before f). 29 (wrf, er) = w -> e (since w and e don't match, and w is on the left). 30 (er, ett) = r -> t (since e matches for both, and r is on the left). 31 (ett, rftt) = e -> r (since e must come before r). 32 33 As well, we want to create an indegree map that counts how man indegrees 34 each node has. For this graph: 35 36 t -> f 37 w -> e 38 r -> t 39 e -> r 40 41 The indegrees are: 42 43 r -> 1 44 t -> 1 45 f -> 1 46 e -> 1 47 w -> 0 48 49 In this case, we find any node with indegree 0 and do a topological sort. 50 So in the above case, we visit w, add it to our output, and then check 51 if its children, in this case, e are visitable. 52 53 e has an indegree of 1, so after w is visited, it is visitable, so 54 we visit e. 55 56 Then, e allows us to visit r, which also has an indegree of 1, so after 57 visiting e, r is visitable. 58 59 Then we visit r, which has a child of t, and we can visit t after visiting 60 r because it has an indegree of 1. 61 62 Then we visit t, which allows us to visit f. 63 64 This allows us to construct the string "wertf", which is the only valid 65 ordering for this example, but other examples may have more orderings. 66 67 We make sure that we've counted every char in the original set of words 68 before returning the joined string. 69 70 """ 71 adj_list = defaultdict(set) 72 indegrees = Counter({c: 0 for word in words for c in word}) 73 74 for l, r in zip(words, words[1:]): 75 for c, d in zip(l, r): 76 if c != d: 77 if d not in adj_list[c]: 78 adj_list[c].add(d) 79 indegrees[d] += 1 80 break 81 else: 82 if len(r) < len(l): 83 return "" 84 85 output = [] 86 q = deque([c for c in indegrees if indegrees[c] == 0]) 87 while q: 88 c = q.popleft() 89 output.append(c) 90 for d in adj_list[c]: 91 indegrees[d] -= 1 92 if indegrees[d] == 0: 93 q.append(d) 94 95 if len(output) < len(indegrees): 96 return "" 97 return "".join(output) 98 99 100# @leet end 101 102 103def test(): 104 assert 2 + 2 == 4
6class Solution: 7 def alienOrder(self, words: list[str]) -> str: 8 """ 9 This question asks us to return an ordering of characters given a set 10 of sorted words. 11 12 First, we describe the relation between the characters. We do this by 13 extracting the first character of each pair that doesn't match, and 14 noting that the left side char comes before the right side. 15 16 For these words: 17 18 wrt 19 wrf 20 er 21 ett 22 rftt 23 24 the pairs would be (wrt, wrf), (wrf, er), (er, ett), (ett, rftt). 25 26 For each pair, we want to find which ones come before, so: 27 28 (wrt, wrf) = t -> f (since wr are the same, t and f are the first differing 29 characters, and t is on the left side of our pair, so t comes before f). 30 (wrf, er) = w -> e (since w and e don't match, and w is on the left). 31 (er, ett) = r -> t (since e matches for both, and r is on the left). 32 (ett, rftt) = e -> r (since e must come before r). 33 34 As well, we want to create an indegree map that counts how man indegrees 35 each node has. For this graph: 36 37 t -> f 38 w -> e 39 r -> t 40 e -> r 41 42 The indegrees are: 43 44 r -> 1 45 t -> 1 46 f -> 1 47 e -> 1 48 w -> 0 49 50 In this case, we find any node with indegree 0 and do a topological sort. 51 So in the above case, we visit w, add it to our output, and then check 52 if its children, in this case, e are visitable. 53 54 e has an indegree of 1, so after w is visited, it is visitable, so 55 we visit e. 56 57 Then, e allows us to visit r, which also has an indegree of 1, so after 58 visiting e, r is visitable. 59 60 Then we visit r, which has a child of t, and we can visit t after visiting 61 r because it has an indegree of 1. 62 63 Then we visit t, which allows us to visit f. 64 65 This allows us to construct the string "wertf", which is the only valid 66 ordering for this example, but other examples may have more orderings. 67 68 We make sure that we've counted every char in the original set of words 69 before returning the joined string. 70 71 """ 72 adj_list = defaultdict(set) 73 indegrees = Counter({c: 0 for word in words for c in word}) 74 75 for l, r in zip(words, words[1:]): 76 for c, d in zip(l, r): 77 if c != d: 78 if d not in adj_list[c]: 79 adj_list[c].add(d) 80 indegrees[d] += 1 81 break 82 else: 83 if len(r) < len(l): 84 return "" 85 86 output = [] 87 q = deque([c for c in indegrees if indegrees[c] == 0]) 88 while q: 89 c = q.popleft() 90 output.append(c) 91 for d in adj_list[c]: 92 indegrees[d] -= 1 93 if indegrees[d] == 0: 94 q.append(d) 95 96 if len(output) < len(indegrees): 97 return "" 98 return "".join(output)
7 def alienOrder(self, words: list[str]) -> str: 8 """ 9 This question asks us to return an ordering of characters given a set 10 of sorted words. 11 12 First, we describe the relation between the characters. We do this by 13 extracting the first character of each pair that doesn't match, and 14 noting that the left side char comes before the right side. 15 16 For these words: 17 18 wrt 19 wrf 20 er 21 ett 22 rftt 23 24 the pairs would be (wrt, wrf), (wrf, er), (er, ett), (ett, rftt). 25 26 For each pair, we want to find which ones come before, so: 27 28 (wrt, wrf) = t -> f (since wr are the same, t and f are the first differing 29 characters, and t is on the left side of our pair, so t comes before f). 30 (wrf, er) = w -> e (since w and e don't match, and w is on the left). 31 (er, ett) = r -> t (since e matches for both, and r is on the left). 32 (ett, rftt) = e -> r (since e must come before r). 33 34 As well, we want to create an indegree map that counts how man indegrees 35 each node has. For this graph: 36 37 t -> f 38 w -> e 39 r -> t 40 e -> r 41 42 The indegrees are: 43 44 r -> 1 45 t -> 1 46 f -> 1 47 e -> 1 48 w -> 0 49 50 In this case, we find any node with indegree 0 and do a topological sort. 51 So in the above case, we visit w, add it to our output, and then check 52 if its children, in this case, e are visitable. 53 54 e has an indegree of 1, so after w is visited, it is visitable, so 55 we visit e. 56 57 Then, e allows us to visit r, which also has an indegree of 1, so after 58 visiting e, r is visitable. 59 60 Then we visit r, which has a child of t, and we can visit t after visiting 61 r because it has an indegree of 1. 62 63 Then we visit t, which allows us to visit f. 64 65 This allows us to construct the string "wertf", which is the only valid 66 ordering for this example, but other examples may have more orderings. 67 68 We make sure that we've counted every char in the original set of words 69 before returning the joined string. 70 71 """ 72 adj_list = defaultdict(set) 73 indegrees = Counter({c: 0 for word in words for c in word}) 74 75 for l, r in zip(words, words[1:]): 76 for c, d in zip(l, r): 77 if c != d: 78 if d not in adj_list[c]: 79 adj_list[c].add(d) 80 indegrees[d] += 1 81 break 82 else: 83 if len(r) < len(l): 84 return "" 85 86 output = [] 87 q = deque([c for c in indegrees if indegrees[c] == 0]) 88 while q: 89 c = q.popleft() 90 output.append(c) 91 for d in adj_list[c]: 92 indegrees[d] -= 1 93 if indegrees[d] == 0: 94 q.append(d) 95 96 if len(output) < len(indegrees): 97 return "" 98 return "".join(output)
This question asks us to return an ordering of characters given a set of sorted words.
First, we describe the relation between the characters. We do this by extracting the first character of each pair that doesn't match, and noting that the left side char comes before the right side.
For these words:
wrt wrf er ett rftt
the pairs would be (wrt, wrf), (wrf, er), (er, ett), (ett, rftt).
For each pair, we want to find which ones come before, so:
(wrt, wrf) = t -> f (since wr are the same, t and f are the first differing characters, and t is on the left side of our pair, so t comes before f). (wrf, er) = w -> e (since w and e don't match, and w is on the left). (er, ett) = r -> t (since e matches for both, and r is on the left). (ett, rftt) = e -> r (since e must come before r).
As well, we want to create an indegree map that counts how man indegrees each node has. For this graph:
t -> f w -> e r -> t e -> r
The indegrees are:
r -> 1 t -> 1 f -> 1 e -> 1 w -> 0
In this case, we find any node with indegree 0 and do a topological sort. So in the above case, we visit w, add it to our output, and then check if its children, in this case, e are visitable.
e has an indegree of 1, so after w is visited, it is visitable, so we visit e.
Then, e allows us to visit r, which also has an indegree of 1, so after visiting e, r is visitable.
Then we visit r, which has a child of t, and we can visit t after visiting r because it has an indegree of 1.
Then we visit t, which allows us to visit f.
This allows us to construct the string "wertf", which is the only valid ordering for this example, but other examples may have more orderings.
We make sure that we've counted every char in the original set of words before returning the joined string.