Skip to content

Topological Sort — Alien Dictionary ​

↗ LeetCode: Alien Dictionary · Hard · pattern chapter →

Asked atMetaAmazonGoogleLinkedInUber

Given words sorted alphabetically in an alien language, return the character order. Return "" if impossible.

Example 1 — words=["wrt","wrf","er","ett","rftt"] → "wertf"Example 2 — words=["z","x"] → "zx"Example 3 — words=["z","x","z"] → "" (cycle)

Constraints — 1 ≤ words.length ≤ 100; 1 ≤ words[i].length ≤ 100; lowercase English. Brute enumerates 26! ≈ 4·10²⁶ character orderings — 10⁹ ops/sec means ~10¹⁰ year (dies before universe end). Topo sort of char-pair graph is O(N·L + 26²) = ~10⁴ ops per input, scales to ~10⁶ ops/sec dictionary validations.

Progressive Hints
Try to solve it yourself first. Reveal hints only when stuck — each hint is progressively more specific.
---
⏱️Interview timer00:00
Practice under interview pressure. Start when you begin reading; stop when you finish. Save best only when you had a full working solution.
Target for interview: Medium = 20-25 min · Hard = 30-40 min · Best time persists on this device only.

Approach 1 — Trial-and-error permutation ​

Try every char ordering. O(26!). Absurd baseline.

Approach 2 — Build precedence graph + Kahn's BFS toposort (canonical) ​

Insight. From each adjacent pair (a, b) in the sorted list, find the first differing char — this is a directed edge a[i] → b[i]. Then topological sort the graph. Return "" if there's a cycle OR if b is a strict prefix of a (invalid ordering).

java
String alienOrder(String[] words) {
    Map<Character, Set<Character>> g = new HashMap<>();
    Map<Character, Integer> indeg = new HashMap<>();
    for (String w : words) for (char c : w.toCharArray()) indeg.putIfAbsent(c, 0);
    for (int i = 0; i + 1 < words.length; i++) {
        String a = words[i], b = words[i+1];
        if (a.length() > b.length() && a.startsWith(b)) return "";
        for (int j = 0; j < Math.min(a.length(), b.length()); j++) {
            if (a.charAt(j) != b.charAt(j)) {
                g.computeIfAbsent(a.charAt(j), k -> new HashSet<>());
                if (g.get(a.charAt(j)).add(b.charAt(j))) indeg.merge(b.charAt(j), 1, Integer::sum);
                break;
            }
        }
    }
    Queue<Character> q = new ArrayDeque<>();
    for (var e : indeg.entrySet()) if (e.getValue() == 0) q.offer(e.getKey());
    StringBuilder sb = new StringBuilder();
    while (!q.isEmpty()) {
        char c = q.poll();
        sb.append(c);
        for (char nxt : g.getOrDefault(c, Set.of()))
            if (indeg.merge(nxt, -1, Integer::sum) == 0) q.offer(nxt);
    }
    return sb.length() == indeg.size() ? sb.toString() : "";
}
Execution Trace
Toposort — words=['wrt','wrf','er','ett','rftt']
stepw0e1r2t3f4edges = w→e, r→t, t→f, e→r
Step 1 / 3extracted from adjacent pairs

Complexity — Time O(C) where C = total characters; Space O(1) (bounded alphabet).


Try it yourself ​

Complexity summary ​

ApproachTimeSpaceGrade
Trial-and-errorO(26!)O(1)trivia
Kahn's BFS toposortO(C)O(1)canonical

When to use which ​

  • "Any valid order" → Kahn's BFS.
  • "Lex-smallest topological order" → replace queue with min-heap.
  • DFS-based alternative → recursion + reverse post-order; same complexity.
✨AI Study CompanionBeta
Was this page helpful?

Released under MIT license.

💡 Quick shortcuts
H HintsR Run JavaA AI Help