words is sorted lexicographically by an unknown alien alphabet. Return a string of its letters in a valid order, or "" if no order is consistent.
Build the same graph. DFS each letter; after visiting everything that must come after it, prepend the letter. A gray (in-progress) letter seen again means a cycle.
1function alienOrder(words: string[]): string {2const adj = new Map<string, Set<string>>();3for (const ch of words.join("")) adj.set(ch, new Set());4for (let i = 0; i + 1 < words.length; i++) {5const [a, b] = [words[i], words[i + 1]];6const k = [...a].findIndex((ch, j) => ch !== b[j]);7if (k === -1 || k >= b.length) { if (a.length > b.length) return ""; continue; }8adj.get(a[k])!.add(b[k]);9}10const state = new Map<string, number>(); // 1 = visiting, 2 = done11const out: string[] = [];12function visit(ch: string): boolean {13if (state.get(ch) === 1) return false;14if (state.get(ch) === 2) return true;15state.set(ch, 1);16for (const next of adj.get(ch)!) if (!visit(next)) return false;17state.set(ch, 2); out.push(ch);18return true;19}20for (const ch of adj.keys()) if (!visit(ch)) return "";21return out.reverse().join("");22}
Collect every letter as a node.
Space: play/pause · ←/→: step