Google — Alien Dictionary (Topological Sort on Characters)
Advertisement
Problem (Google Top-10)
Given a list of words sorted in an alien language, derive the character ordering. Return any valid ordering, or "" if invalid (cycle detected).
Example:
words = ["wrt","wrf","er","ett","rftt"]
→ "wertf"
Key Insight — Build Graph from Adjacent Words
Compare consecutive words: find first differing char → edge a → b (a comes before b). If word2 is a prefix of word1 (word1 longer), invalid → return "". Then run Kahn's topological sort BFS.
Solutions
Python
from collections import defaultdict, deque
def alienOrder(words):
adj = defaultdict(set)
in_degree = {c: 0 for w in words for c in w}
for i in range(len(words) - 1):
w1, w2 = words[i], words[i+1]
min_len = min(len(w1), len(w2))
if len(w1) > len(w2) and w1[:min_len] == w2[:min_len]:
return ""
for j in range(min_len):
if w1[j] != w2[j]:
if w2[j] not in adj[w1[j]]:
adj[w1[j]].add(w2[j])
in_degree[w2[j]] += 1
break
q = deque([c for c in in_degree if in_degree[c] == 0])
order = []
while q:
c = q.popleft()
order.append(c)
for nb in adj[c]:
in_degree[nb] -= 1
if in_degree[nb] == 0:
q.append(nb)
return ''.join(order) if len(order) == len(in_degree) else ""
JavaScript
function alienOrder(words) {
const adj = new Map(), inDeg = new Map();
for (const w of words) for (const c of w) if (!inDeg.has(c)) { inDeg.set(c, 0); adj.set(c, new Set()); }
for (let i = 0; i < words.length-1; i++) {
const [w1,w2] = [words[i],words[i+1]];
if (w1.length>w2.length && w1.startsWith(w2)) return "";
for (let j=0; j<Math.min(w1.length,w2.length); j++) {
if (w1[j]!==w2[j]) { if(!adj.get(w1[j]).has(w2[j])){adj.get(w1[j]).add(w2[j]);inDeg.set(w2[j],inDeg.get(w2[j])+1);} break; }
}
}
const q=[...inDeg.entries()].filter(([,v])=>v===0).map(([k])=>k), res=[];
while(q.length){const c=q.shift();res.push(c);for(const nb of adj.get(c)){inDeg.set(nb,inDeg.get(nb)-1);if(inDeg.get(nb)===0)q.push(nb);}}
return res.length===inDeg.size?res.join(""):"";
}
Java
import java.util.*;
public String alienOrder(String[] words) {
Map<Character,Set<Character>> adj = new HashMap<>();
Map<Character,Integer> deg = new HashMap<>();
for (String w : words) for (char c : w.toCharArray()) { adj.putIfAbsent(c,new HashSet<>()); deg.putIfAbsent(c,0); }
for (int i=0; i<words.length-1; i++) {
String w1=words[i], w2=words[i+1];
int mn=Math.min(w1.length(),w2.length());
if (w1.length()>w2.length() && w1.substring(0,mn).equals(w2)) return "";
for (int j=0; j<mn; j++) if (w1.charAt(j)!=w2.charAt(j)) { if(adj.get(w1.charAt(j)).add(w2.charAt(j))) deg.merge(w2.charAt(j),1,Integer::sum); break; }
}
Queue<Character> q=new LinkedList<>(); StringBuilder sb=new StringBuilder();
for (char c : deg.keySet()) if (deg.get(c)==0) q.offer(c);
while (!q.isEmpty()) { char c=q.poll(); sb.append(c); for (char nb : adj.get(c)) { deg.merge(nb,-1,Integer::sum); if(deg.get(nb)==0) q.offer(nb); } }
return sb.length()==deg.size()?sb.toString():"";
}
C++
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <string>
#include <vector>
using namespace std;
string alienOrder(vector<string>& words) {
unordered_map<char,unordered_set<char>> adj;
unordered_map<char,int> deg;
for (auto& w : words) for (char c : w) { adj[c]; deg[c]=deg.count(c)?deg[c]:0; }
for (int i=0; i<(int)words.size()-1; i++) {
auto& w1=words[i]; auto& w2=words[i+1];
int mn=min(w1.size(),w2.size());
if (w1.size()>w2.size()&&w1.substr(0,mn)==w2) return "";
for (int j=0; j<mn; j++) if (w1[j]!=w2[j]) { if(!adj[w1[j]].count(w2[j])){adj[w1[j]].insert(w2[j]);deg[w2[j]]++;} break; }
}
queue<char> q; string res;
for (auto& [c,d] : deg) if (d==0) q.push(c);
while (!q.empty()) { char c=q.front(); q.pop(); res+=c; for (char nb : adj[c]) if (--deg[nb]==0) q.push(nb); }
return res.size()==deg.size()?res:"";
}
C
/* C: adjacency matrix for 26 chars + in-degree array + queue-based Kahn's */
Complexity
| Phase | Time |
|---|---|
| Build graph | O(N·L) |
| Topological sort | O(V+E) ≤ O(26²) |
| Total | O(N·L) |
Advertisement