Google — Alien Dictionary (Topological Sort on Characters)

Sanjeev SharmaSanjeev Sharma
3 min read

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

PhaseTime
Build graphO(N·L)
Topological sortO(V+E) ≤ O(26²)
TotalO(N·L)

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro