Forberedelse til kodeintervjuer · leksjon

Gjennomgang av vanskelige problemer: Word Ladder II og Alien Dictionary

Ta for Dem to vanskelige problemer fra start til slutt – «word-ladder-II» med BFS og tilbakesporing, og «alien-dictionary» med topologisk sortering – med en fullstendig forklaring.

Leksjon 4 av 413 trinn

Gjennomgang av vanskelige problemer: Word Ladder II og Alien Dictionary er en gratis leksjon i Forberedelse til kodeintervjuer på CoddyKit. Dette er leksjon 4 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Forberedelse til kodeintervjuer, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Forberedelse til kodeintervjuer inneholder totalt 4 leksjoner.

Hvorfor vanskelige oppgaver er annerledes

Vanskelige LeetCode-oppgaver skiller seg fra middels vanskelige oppgaver på to viktige måter: (1) De krever at De kombinerer to eller flere algoritmiske teknikker, og (2) den optimale løsningen er ofte ikke åpenbar ut fra oppgaveteksten alene – De må se forbi den overfladiske beskrivelsen og finne den underliggende graf- eller DP-strukturen. Word Ladder II og Alien Dictionary er klassiske vanskelige oppgaver som stadig dukker opp i FAANG-intervjuer.

Fremgangsmåten for vanskelige oppgaver er å ikke forsøke å se hele løsningen med én gang. Del den i stedet opp i delproblemer, identifiser strukturen til hvert delproblem, løs dem hver for seg, og sett dem deretter sammen. Denne modulære tenkemåten er nøkkelen til å løse vanskelige oppgaver under press.

# Hard problem meta-strategy
strategy = [
    '1. Read the problem 2x — hard problems often have subtle constraints',
    '2. Model it as a known structure: graph? DP table? sorted order?',
    '3. Break into sub-problems: separate the graph-building from the traversal',
    '4. Solve sub-problems in order, verifying each before connecting',
    '5. Handle the edge case where no solution exists (empty result, -1, [])',
    '6. Optimise only after the correct but slow solution works',
]
print('Hard problem meta-strategy:')
for step in strategy:
    print(f'  {step}')

Word Ladder II: Oppgavetekst

Word Ladder II (LeetCode 126): Gitt et startord, et sluttord og en ordliste skal De finne alle korteste transformasjonssekvenser fra start til slutt. Hvert trinn endrer nøyaktig ett tegn, og hvert mellomliggende ord må finnes i ordlisten. Dette er betydelig vanskeligere enn Word Ladder I, som bare finner én korteste sti, fordi De må finne alle optimale stier.

Eksempel: beginWord='hit', endWord='cog', wordList=['hot','dot','dog','lot','log','cog'] → [['hit','hot','dot','dog','cog'],['hit','hot','lot','log','cog']]. Begge har lengde 5.

# Word Ladder II problem breakdown
begin_word = 'hit'
end_word = 'cog'
word_list = ['hot','dot','dog','lot','log','cog']

# What we need:
# 1. Build a graph: word -> set of words that differ by one character
# 2. BFS to find the MINIMUM number of steps (shortest path distance)
# 3. DFS/backtracking to enumerate ALL paths of that minimum length

# Key insight: BFS finds shortest distance; DFS reconstructs all shortest paths
# Two-phase approach:
print('Phase 1: BFS from begin_word to find min distance to each word')
print('Phase 2: DFS/backtrack from end_word using only edges that decrease distance')
print()
print(f'Input: {begin_word} -> {end_word}')
print(f'Word list: {word_list}')
print('Expected: [[hit,hot,dot,dog,cog],[hit,hot,lot,log,cog]]')

Word Ladder II: BFS-fase

I fase 1 kjører De BFS nivå for nivå fra startordet. På hvert nivå finner De alle naboer (ord som skiller seg med ett tegn). De registrerer nivået (avstanden fra starten) der hvert ord nås for første gang. De stopper IKKE når De når sluttordet – De fortsetter til slutten av nivået der end_word ble funnet, slik at alle korteste stier blir utforsket.

Det er avgjørende å bygge en parents-ordbok som knytter hvert ord til mengden av ord som kan stå foran det i en korteste sti. Dette er grafen vi bruker i fase 2 til tilbakesporingen.

from collections import defaultdict, deque

def find_parents(begin, end, word_set):
    parents = defaultdict(set)
    layer = {begin}
    found = False

    while layer and not found:
        next_layer = set()
        for word in layer:
            for i in range(len(word)):
                for c in 'abcdefghijklmnopqrstuvwxyz':
                    new_word = word[:i] + c + word[i+1:]
                    if new_word in word_set and new_word not in parents:
                        next_layer.add(new_word)
                        parents[new_word].add(word)
                        if new_word == end:
                            found = True
        layer = next_layer
    return parents if found else {}

words = {'hot','dot','dog','lot','log','cog'}
parents = find_parents('hit', 'cog', words)
print('Parents map (which words can precede each word):')
for word, preds in sorted(parents.items()):
    print(f'  {word}: {preds}')

Word Ladder II: DFS-fase med tilbakesporing

I fase 2 bruker De DFS-backtracking fra sluttordet og følger parents-kartet baklengs. De bygger stier fra slutt til start og snur dem deretter. Når De når startordet, har De funnet en komplett korteste sti. Parents-kartet garanterer at alle stiene som blir funnet, har minimumslengde – De kan ikke «avvike» til en lengre sti.

Denne tofasede fremgangsmåten (BFS for nivåer, DFS for rekonstruksjon av stier) er standardløsningen og kjører i O(n × L × 26) for BFS, der n = størrelsen på ordlisten og L = ordlengden, pluss O(K × L) for DFS, der K = antallet korteste stier.

def find_ladders(beginWord, endWord, wordList):
    word_set = set(wordList)
    if endWord not in word_set:
        return []

    # Phase 1: BFS to build parents map
    parents = defaultdict(set)
    layer = {beginWord}
    found = False
    visited = {beginWord}

    while layer and not found:
        next_layer = set()
        for word in layer:
            for i in range(len(word)):
                for c in 'abcdefghijklmnopqrstuvwxyz':
                    nw = word[:i] + c + word[i+1:]
                    if nw in word_set and nw not in visited:
                        next_layer.add(nw)
                        parents[nw].add(word)
                        if nw == endWord: found = True
        visited |= next_layer
        layer = next_layer

    # Phase 2: DFS backtrack from endWord to beginWord
    result = []
    def dfs(word, path):
        if word == beginWord:
            result.append(path[::-1])
            return
        for parent in parents[word]:
            dfs(parent, path + [parent])
    dfs(endWord, [endWord])
    return result

print(find_ladders('hit','cog',['hot','dot','dog','lot','log','cog']))

Alien Dictionary: Oppgavetekst

Alien Dictionary (LeetCode 269): Gitt en liste med ord som er sortert leksikografisk på et fremmed språk, skal De finne rekkefølgen på tegnene i språket. Returner tegnrekkefølgen som en streng. Hvis ingen gyldig rekkefølge finnes (fordi begrensningene er motstridende), returneres en tom streng.

Eksempel: ['wrt','wrf','er','ett','rftt'] → 'wertf'. Ved å sammenligne ord som står ved siden av hverandre får vi: 't' < 'f' (fra wrt og wrf), 'w' < 'e' (fra wrt og er), 'r' < 't' (fra er og ett), 'e' < 'r' (fra ett og rftt). Dette er en topologisk sortering av disse begrensningene på tegnrekkefølgen.

words = ['wrt', 'wrf', 'er', 'ett', 'rftt']
# Compare adjacent pairs to extract ordering:
# wrt vs wrf: first diff at index 2: t < f  (t comes before f)
# wrf vs er:  first diff at index 0: w < e  (w comes before e)
# er  vs ett: first diff at index 1: r < t  (r comes before t)
# ett vs rftt:first diff at index 0: e < r  (e comes before r)

ordering_constraints = [
    ('t', 'f', 'from wrt vs wrf'),
    ('w', 'e', 'from wrf vs er'),
    ('r', 't', 'from er vs ett'),
    ('e', 'r', 'from ett vs rftt'),
]
print('Ordering constraints extracted from adjacent word pairs:')
for a, b, source in ordering_constraints:
    print(f'  {a} -> {b}  ({source})')
print('\nThis is a directed graph: find topological order = alien alphabet order')

Alien Dictionary: Bygge grafen

Det første trinnet er å trekke ut begrensningene: sammenlign hvert par av ord som står ved siden av hverandre, finn det første tegnet som er forskjellig, og legg til en rettet kant fra det minste til det største tegnet. Hvis ett ord er et prefiks av det neste ordet, men er lengre enn det (for eksempel «abc» før «ab»), er inndataene ugyldige – returner en tom streng umiddelbart.

Alle tegn som forekommer i ordlisten, er noder i grafen, selv om de ikke har noen begrensninger på rekkefølgen. Disse isolerte nodene kan plasseres hvor som helst i den endelige rekkefølgen.

from collections import defaultdict

def build_alien_graph(words):
    adj = defaultdict(set)    # char -> set of chars that come after it
    in_degree = {c: 0 for word in words for c in word}

    for i in range(len(words) - 1):
        w1, w2 = words[i], words[i+1]
        min_len = min(len(w1), len(w2))
        found_diff = False
        for j in range(min_len):
            if w1[j] != w2[j]:
                if w2[j] not in adj[w1[j]]:   # avoid duplicate edges
                    adj[w1[j]].add(w2[j])
                    in_degree[w2[j]] += 1
                found_diff = True
                break
        if not found_diff and len(w1) > len(w2):
            return {}, {}   # invalid: 'abc' before 'ab'
    return adj, in_degree

words = ['wrt', 'wrf', 'er', 'ett', 'rftt']
adj, in_degree = build_alien_graph(words)
print('Adjacency list (directed):', {k: list(v) for k, v in adj.items()})
print('In-degrees:', in_degree)

Alien Dictionary: Topologisk sortering

Når grafen er bygget, bruker De Kahns BFS-topologiske sortering: initialiser en kø med alle tegn som har inngrad 0 (ingen forutsetninger). Behandle hvert tegn, og reduser inngradet til etterfølgerne. Når inngradet til en etterfølger når 0, legger De den i køen. Samle tegnene i behandlingsrekkefølge – dette er den fremmede alfabetiske rekkefølgen.

Hvis resultatet inneholder alle tegnene, har vi en gyldig rekkefølge. Hvis det inneholder færre tegn enn forventet, finnes det en syklus – begrensningene er motstridende, og vi returnerer en tom streng.

from collections import deque, defaultdict

def alien_order(words):
    adj = defaultdict(set)
    in_degree = {c: 0 for word in words for c in word}

    for i in range(len(words) - 1):
        w1, w2 = words[i], words[i + 1]
        min_len = min(len(w1), len(w2))
        found = False
        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
                found = True; break
        if not found and len(w1) > len(w2):
            return ''    # invalid: 'abc' before 'ab'

    # Kahn's BFS topological sort
    queue = deque([c for c in in_degree if in_degree[c] == 0])
    result = []
    while queue:
        c = queue.popleft()
        result.append(c)
        for neighbor in sorted(adj[c]):   # sort for determinism
            in_degree[neighbor] -= 1
            if in_degree[neighbor] == 0:
                queue.append(neighbor)

    return ''.join(result) if len(result) == len(in_degree) else ''

print(alien_order(['wrt','wrf','er','ett','rftt']))  # e.g., 'wertf'
print(alien_order(['z','x']))                         # 'zx'
print(alien_order(['z','x','z']))                     # '' (cycle z->x->z)

Håndtering av kanttilfeller: Begge oppgavene

Både Word Ladder II og Alien Dictionary har subtile kanttilfeller som fører til feil svar hvis de ikke håndteres:

  • Word Ladder II: beginWord og endWord er like (returner [[beginWord]] eller en sekvens med lengde 1). endWord finnes ikke i wordList (returner tomt resultat). Ingen sti finnes (returner tomt resultat).
  • Alien Dictionary: duplikatord (trekk ikke ut noen begrensning). Ett enkelt ord (returner alle unike tegn). Syklus i begrensningene (returner ''). Et ord er et lengre prefiks av det neste ordet (ugyldige inndata, returner ''). Alle tegn er isolerte (returner en hvilken som helst rekkefølge).
# Edge case tests for Word Ladder II
def test_word_ladder_edge_cases():
    from collections import defaultdict
    def find_ladders(begin, end, word_list):
        # [abbreviated implementation for testing]
        if end not in word_list: return []
        if begin == end: return [[begin]]
        return []  # placeholder

    tests = [
        ('hit', 'cog', ['hot','dot','dog','lot','log'], []),  # no path (cog missing)
        ('hit', 'hit', ['hit'], [['hit']]),                   # begin==end
        ('a',   'c',  ['a','b','c'], [['a','c']]),            # short words
    ]
    for begin, end, wl, expected in tests:
        result = find_ladders(begin, end, wl)
        print(f'{begin}->{end}: result={result}')

# Edge case tests for Alien Dictionary
def test_alien_edge_cases():
    from collections import defaultdict, deque
    # (using alien_order from previous scene)
    tests = [
        (['abc', 'ab'], ''),          # 'abc' before 'ab' = invalid
        (['a'],         'a'),          # single word
        (['z','z'],     'z'),          # duplicate: no constraint
    ]
    print('Alien dictionary edge cases:')
    for words, expected in tests:
        print(f'  {words} -> expected: "{expected}"')

test_word_ladder_edge_cases()
test_alien_edge_cases()

Kompleksitetsanalyse: Begge oppgavene

Kompleksiteten til Word Ladder II: BFS-fasen kjører i O(n × L × 26), der n = antallet ord i listen og L = ordlengden. For hvert ord på hvert BFS-nivå genererer vi 26L kandidatord og sjekker om de finnes i ordmengden (O(1) per sjekk). DFS-fasen er O(K × L), der K = antallet korteste stier (kan i teorien være eksponentielt).

Kompleksiteten til Alien Dictionary: Å bygge grafen er O(C), der C = det totale antallet tegn i alle ord. Topologisk sortering er O(V + E), der V = antallet unike tegn og E = antallet begrensninger på rekkefølgen. Totalt blir dette O(C), som er O(totalt antall tegn i inndataene).

# Complexity analysis for both problems
complexities = [
    {
        'problem': 'Word Ladder II',
        'time': 'O(n * L * 26) BFS + O(K * L) DFS backtracking',
        'space': 'O(n * L) for word set + parents map',
        'notes': 'K (number of shortest paths) can be exponential in pathological cases',
    },
    {
        'problem': 'Alien Dictionary',
        'time': 'O(C) where C = total characters in all words',
        'space': 'O(V + E) for adjacency list',
        'notes': 'V <= 26 (alphabet), E <= V^2 = 676; often treated as O(C) total',
    },
]
for c in complexities:
    print(f'{c["problem"]}:')
    print(f'  Time:  {c["time"]}')
    print(f'  Space: {c["space"]}')
    print(f'  Notes: {c["notes"]}')
    print()

Mønsteroppsummering: To gjenbrukbare maler

Begge oppgavene lærer bort gjenbrukbare mønstre. Word Ladder II = BFS for avstander + DFS for rekonstruksjon av stier: Dette mønsteret dukker opp når De trenger alle korteste stier i en uvektet graf. Bygg foreldretilordningen under BFS, og spor deretter bakover fra målet til kilden.

Alien Dictionary = uttrekking av kanter + topologisk sortering: Dette mønsteret dukker opp når De får en sortert sekvens og må utlede de underliggende reglene for rekkefølgen. Trekk ut rettede begrensninger fra par av ord som står ved siden av hverandre, og bruk deretter Kahns algoritme. Returner '' ved oppdagelse av en syklus (umulig rekkefølge).

# Pattern templates
print('Template 1: All Shortest Paths in Unweighted Graph')
template_1 = '''
1. BFS from source, recording parents[node] = set of nodes that lead to node
2. Continue each BFS level fully (do not stop at first endNode reach)
3. DFS backtrack from endNode, following parents map
4. Reverse each path found (built end->start, need start->end)
'''
print(template_1)

print('Template 2: Infer Ordering from Sorted Sequence')
template_2 = '''
1. Compare adjacent pairs, extract first differing element as directed constraint
2. Build adjacency list + in-degree map
3. Check for invalid input (prefix longer than successor)
4. Kahn's BFS topological sort
5. If result length < number of nodes => cycle => return invalid
'''
print(template_2)

Slik bygger De selvtillit i vanskelige oppgaver

Vanskelige oppgaver virker umulige i begynnelsen, men blir håndterbare med riktig mental modell. De viktigste innsiktene er:

  • Skill mellom ansvarsområder: løs hvert delproblem separat før De setter dem sammen
  • Kjenn byggeklossene Deres: BFS/DFS, topologisk sortering, Dijkstra, DP-tabeller – vanskelige oppgaver kombinerer disse på uventede måter
  • Begynn med eksempler: gå manuelt gjennom oppgaven med et lite eksempel for å oppdage den underliggende strukturen
  • Kontroller delproblemene: etter at De har implementert fase 1 (bygging av grafen), skriv ut grafen og kontroller den manuelt før De går videre til fase 2
# Hard problem confidence-building practice plan
practice_plan = [
    ('Week 1', 'BFS/DFS fundamentals', ['Number of Islands', 'Clone Graph', 'Word Ladder I']),
    ('Week 2', 'Topological sort', ['Course Schedule I & II', 'Alien Dictionary (easy)']),
    ('Week 3', 'All-paths problems', ['All Paths to Target', 'Word Ladder II (hard)']),
    ('Week 4', 'Hard combos', ['Minimum Window Substring', 'Serialize/Deserialize Tree']),
]
print('4-week hard problem practice plan:')
for week, theme, problems in practice_plan:
    print(f'\n{week} — {theme}:')
    for p in problems:
        print(f'  - {p}')

print('\nAfter each problem, write:')
print('  1. The pattern it belongs to')
print('  2. The 2-3 key sub-problems')
print('  3. One insight you would not have had before solving it')

Hurtigsjekk

Test forståelsen Deres av Data Structures & Algorithms — Coding Interview Prep-konseptene fra denne leksjonen.

Oppsummering av leksjonen

I denne leksjonen lærte De at Word Ladder II bruker BFS til å bygge et parents-kart over alle forgjengerne til de korteste stiene, og deretter DFS-backtracking til å finne alle korteste stier ved å følge parents fra slutt til start, at Alien Dictionary trekker ut rettede begrensninger fra par av ord som står ved siden av hverandre, og bruker Kahns topologiske sortering til å ordne tegnene, med tom streng som resultat når en syklus oppdages, og at vanskelige oppgaver kan deles opp i flere delproblemer – bygging av grafen, avstandsberegning og rekonstruksjon av stier – som hver løses separat med kjente algoritmer. De har nå fullført hele DSA Interview Prep-kurset. Bruk alle mønstrene og teknikkene fra dette sporet i intervjuene Deres med selvtillit.

Gratis å komme i gang

Lær deg Forberedelse til kodeintervjuer med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
90
Leksjoner
360

Ofte stilte spørsmål

Er leksjonen «Gjennomgang av vanskelige problemer: Word Ladder II og Alien Dictionary» gratis?

Ja – hele teksten i «Gjennomgang av vanskelige problemer: Word Ladder II og Alien Dictionary» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Forberedelse til kodeintervjuer-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Forberedelse til kodeintervjuer inneholder totalt 4 leksjoner.

Hva lærer jeg i «Gjennomgang av vanskelige problemer: Word Ladder II og Alien Dictionary»?

Ta for Dem to vanskelige problemer fra start til slutt – «word-ladder-II» med BFS og tilbakesporing, og «alien-dictionary» med topologisk sortering – med en fullstendig forklaring. Du øver på Forberedelse til kodeintervjuer med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Forberedelse til kodeintervjuer?

Ingen tidligere erfaring er nødvendig. Forberedelse til kodeintervjuer på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.

Hvor lang tid tar leksjonen «Gjennomgang av vanskelige problemer: Word Ladder II og Alien Dictionary»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Forberedelse til kodeintervjuer-leksjonen?

Ja. Alle Forberedelse til kodeintervjuer-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Hurtigguide til mønstergjenkjenning
  2. Tidsbegrenset prøveintervju: enkle og middels vanskelige problemer
  3. Håndtering av spesialtilfeller og kommunikasjon i intervjuet
  4. Gjennomgang av vanskelige problemer: Word Ladder II og Alien Dictionary
← Tilbake til Forberedelse til kodeintervjuer