Edges from adjacent words + Kahn's
Time O(total characters + 26 log 26) Space O(26²)Register every letter. For each adjacent pair, find the first difference a ≠ b and add edge a → b. Run Kahn's with a PriorityQueue. If not every letter is output, there's a cycle.
import java.util.*;
class Solution {
public String alienOrder(String[] words) {
Map<Character, Set<Character>> adj = new HashMap<>();
Map<Character, Integer> indeg = new HashMap<>();
for (String w : words)
for (char c : w.toCharArray()) { adj.putIfAbsent(c, new HashSet<>()); indeg.putIfAbsent(c, 0); }
for (int i = 0; i + 1 < words.length; i++) {
String a = words[i], b = words[i + 1];
int len = Math.min(a.length(), b.length()), j = 0;
while (j < len && a.charAt(j) == b.charAt(j)) j++;
if (j == len) {
if (a.length() > b.length()) return ""; // "abc" before "ab" is impossible
continue;
}
if (adj.get(a.charAt(j)).add(b.charAt(j))) indeg.merge(b.charAt(j), 1, Integer::sum);
}
PriorityQueue<Character> ready = new PriorityQueue<>();
for (Map.Entry<Character, Integer> e : indeg.entrySet()) if (e.getValue() == 0) ready.offer(e.getKey());
StringBuilder sb = new StringBuilder();
while (!ready.isEmpty()) {
char c = ready.poll();
sb.append(c);
for (char d : adj.get(c)) if (indeg.merge(d, -1, Integer::sum) == 0) ready.offer(d);
}
return sb.length() == indeg.size() ? sb.toString() : "";
}
}Verdict: Only adjacent pairs are needed; others follow transitively.