|
| 1 | +export class Solution { |
| 2 | + alienOrder(words: string[]): string { |
| 3 | + const indegree = new Map<string, number>(); |
| 4 | + const graph = new Map<string, Set<string>>(); |
| 5 | + |
| 6 | + for (const word of words) { |
| 7 | + for (const ch of word) { |
| 8 | + if (graph.has(ch)) continue; |
| 9 | + graph.set(ch, new Set<string>()); |
| 10 | + indegree.set(ch, 0); |
| 11 | + } |
| 12 | + } |
| 13 | + |
| 14 | + for (let i = 0; i < words.length - 1; i++) { |
| 15 | + const word1 = words[i]; |
| 16 | + const word2 = words[i + 1]; |
| 17 | + |
| 18 | + let pointer = 0; |
| 19 | + while (pointer < word1.length && pointer < word2.length && word1[pointer] === word2[pointer]) { |
| 20 | + pointer++; |
| 21 | + } |
| 22 | + |
| 23 | + if (pointer < word1.length && pointer === word2.length) { |
| 24 | + return ""; |
| 25 | + } |
| 26 | + |
| 27 | + if (pointer < word1.length && pointer < word2.length) { |
| 28 | + const neighbors = graph.get(word1[pointer])!; |
| 29 | + if (!neighbors.has(word2[pointer])) { |
| 30 | + neighbors.add(word2[pointer]); |
| 31 | + indegree.set(word2[pointer], (indegree.get(word2[pointer]) || 0) + 1); |
| 32 | + } |
| 33 | + } |
| 34 | + } |
| 35 | + |
| 36 | + const queue: string[] = []; |
| 37 | + const result: string[] = []; |
| 38 | + |
| 39 | + for (const [ch, degree] of indegree) { |
| 40 | + if (degree === 0) { |
| 41 | + queue.push(ch); |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + while (queue.length > 0) { |
| 46 | + const current = queue.shift()!; |
| 47 | + result.push(current); |
| 48 | + |
| 49 | + for (const neighbor of graph.get(current) || []) { |
| 50 | + indegree.set(neighbor, (indegree.get(neighbor) || 0) - 1); |
| 51 | + if (indegree.get(neighbor) === 0) { |
| 52 | + queue.push(neighbor); |
| 53 | + } |
| 54 | + } |
| 55 | + } |
| 56 | + |
| 57 | + if (indegree.size === result.length) { |
| 58 | + return result.join(""); |
| 59 | + } |
| 60 | + |
| 61 | + return ""; |
| 62 | + } |
| 63 | +} |
0 commit comments