Prefixsökning och Starts-With
Lägg till en starts_with-metod som returnerar true om något infogat ord delar ett angivet prefix och använd den för att implementera förslag på automatisk komplettering.
Prefixsökning och Starts-With är en gratis lektion i DSA Interview Prep på CoddyKit. Detta är lektion 2 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för DSA Interview Prep, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i DSA Interview Prep innehåller totalt 4 lektioner.
Prefixfrågornas styrka
Triets främsta fördel jämfört med en hash map är effektiv prefixsökning. En prefixfråga kan besvara: ”hur många lagrade ord börjar med det här prefixet?”, ”vilka är alla lagrade ord med det här prefixet?” eller helt enkelt ”finns det något ord med det här prefixet?”. Dessa frågor har O(p)-komplexitet, där p är prefixets längd, oberoende av det totala antalet lagrade ord — vilket gör tries idealiska för autocomplete och sökförslag.
Metoden starts_with
starts_with(prefix) returnerar True om något lagrat ord börjar med det angivna prefixet. Gå igenom trien genom att följa varje tecken i prefixet. Om alla tecken kan följas utan att någon kant saknas finns prefixet, och minst ett ord börjar med det. Implementationen är identisk med search, förutom att vi returnerar True så snart genomgången är klar — vi kontrollerar inte is_end.
class TrieNode:
def __init__(self):
self.children = {}
self.is_end = False
class Trie:
def __init__(self):
self.root = TrieNode()
def insert(self, word):
node = self.root
for c in word:
if c not in node.children:
node.children[c] = TrieNode()
node = node.children[c]
node.is_end = True
def starts_with(self, prefix):
node = self.root
for c in prefix:
if c not in node.children:
return False
node = node.children[c]
return True
t = Trie()
for w in ['hello','help','world','word']:
t.insert(w)
print(t.starts_with('hel')) # True
print(t.starts_with('wor')) # True
print(t.starts_with('xyz')) # FalseAutocomplete: hitta alla ord med ett prefix
För att implementera autocomplete går du till prefixets slutnod och gör sedan en DFS eller BFS från den noden för att samla in alla ord som grenar ut från den. Lägg till prefixet framför varje insamlat suffix för att återskapa de fullständiga orden. Detta tar O(p + W) tid, där W är det totala antalet tecken i alla matchande ord.
class TrieNode:
def __init__(self):
self.children = {}
self.is_end = False
class Trie:
def __init__(self):
self.root = TrieNode()
def insert(self, word):
node = self.root
for c in word:
if c not in node.children:
node.children[c] = TrieNode()
node = node.children[c]
node.is_end = True
def autocomplete(self, prefix):
node = self.root
for c in prefix:
if c not in node.children:
return []
node = node.children[c]
# DFS from prefix end node
results = []
def dfs(n, path):
if n.is_end:
results.append(prefix + path)
for char, child in n.children.items():
dfs(child, path + char)
dfs(node, '')
return results
t = Trie()
for w in ['apple','app','application','apply','apt']:
t.insert(w)
print(t.autocomplete('app')) # ['app','apple','apply','application']Returnera sorterade förslag
För sorterade autocomplete-förslag går du igenom barnen i alfabetisk ordning under DFS, genom att iterera över sorted(node.children.items()). Eftersom barnen lagras i en dictionary tillkommer overhead på O(ALPHABET_SIZE × depth), men resultaten garanteras komma i lexikografisk ordning. En arraybaserad trie går alltid igenom barnen i alfabetisk ordning, eftersom indexen 0–25 är ordnade.
def dfs_sorted(node, prefix, results):
if node.is_end:
results.append(prefix)
for char in sorted(node.children.keys()): # alphabetical order
dfs_sorted(node.children[char], prefix + char, results)
print('Iterating children in sorted order gives lex-sorted suggestions')Autocomplete-förslag med topp-k
För topp-k-förslag efter frekvens utökar du varje nod med ett antal som anger hur många gånger ordet som slutar där har sökts efter. När du samlar in förslag använder du en max-heap med storleken k. Detta minskar resultatmängden från DFS, O(W), till O(k) utan att materialisera alla matchningar. Sökmotorer i verkligheten kombinerar triegenomgång av prefix med frekvensdata för att snabbt skapa relevanta förslag.
Implementera trien för LeetCode 208
LeetCode 208, 'Implement Trie (Prefix Tree)', kräver exakt följande: insert(word), search(word) som returnerar ett booleskt värde för exakt matchning, och startsWith(prefix) som returnerar ett booleskt värde för prefixmatchning. Detta är den klassiska trie-implementeringen. Kom ihåg: search kräver is_end=True; startsWith kräver endast att prefixvägen finns.
class Trie:
def __init__(self):
self.root = {}
def insert(self, word):
node = self.root
for c in word:
if c not in node:
node[c] = {}
node = node[c]
node['#'] = True # '#' marks word end
def search(self, word):
node = self.root
for c in word:
if c not in node: return False
node = node[c]
return '#' in node
def startsWith(self, prefix):
node = self.root
for c in prefix:
if c not in node: return False
node = node[c]
return True
t = Trie()
t.insert('apple')
print(t.search('apple')) # True
print(t.search('app')) # False
print(t.startsWith('app')) # TrueAnvända '#' som slutmarkör (dictionary-trie)
En elegant genväg är att lagra trien som nästlade dictionary-objekt med en särskild sentinel-nyckel, till exempel '#', för att markera ordslut. Då behövs ingen TrieNode-klass. Detta är kompakt och passar bra i intervjuer, men är något mindre läsbart än explicita TrieNode-objekt. Båda implementationerna är godtagbara; dictionary-versionen går snabbare att skriva under tidspress.
Längsta gemensamma prefix med trie
För att hitta det längsta gemensamma prefixet i en lista med strängar infogar du alla strängar i trien och går sedan från roten längs den enda väg som finns så länge som: (1) den aktuella noden har exakt ett barn och (2) is_end är False. Stanna så snart något av villkoren inte längre gäller. Den följda vägen är det längsta gemensamma prefixet.
class TrieNode:
def __init__(self):
self.children = {}
self.is_end = False
def longest_common_prefix(words):
root = TrieNode()
for word in words:
node = root
for c in word:
if c not in node.children:
node.children[c] = TrieNode()
node = node.children[c]
node.is_end = True
prefix = []
node = root
while len(node.children) == 1 and not node.is_end:
char, node = next(iter(node.children.items()))
prefix.append(char)
return ''.join(prefix)
print(longest_common_prefix(['flower','flow','flight'])) # 'fl'
print(longest_common_prefix(['dog','racecar','car'])) # ''Problemet Replace Words
Replace Words (LeetCode 648): givet en dictionary med rotord och en mening ska du ersätta varje ord i meningen med det kortaste matchande rotordet från dictionaryn. Infoga alla rotord i en trie. För varje ord i meningen går du igenom trien tills slutet på ett rotord hittas — returnera då det rotordet som ersättning. Om inget rotord matchar behåller du det ursprungliga ordet. Detta körs på O(total chars) jämfört med O(n × m) för brute force.
class TrieNode:
def __init__(self):
self.children = {}
self.is_end = False
def replaceWords(dictionary, sentence):
root = TrieNode()
for word in dictionary:
node = root
for c in word:
if c not in node.children:
node.children[c] = TrieNode()
node = node.children[c]
node.is_end = True
def find_root(word):
node = root
for i, c in enumerate(word):
if c not in node.children: break
node = node.children[c]
if node.is_end:
return word[:i+1]
return word
return ' '.join(find_root(w) for w in sentence.split())
print(replaceWords(['cat','bat','rat'], 'the cattle was rattled by the battery'))Problemet Map Sum Pairs
Map Sum (LeetCode 677): infoga nyckel-värde-par och returnera summan av alla värden vars nycklar har ett givet prefix. Utöka varje TrieNode med ett val-fält. Vid insert går du till slutet och anger värdet; vid sum-frågor går du till prefixets slutnod och summerar alla val-fält under den med DFS. Alternativt kan du lagra den kumulativa summan i varje nod under insättningen för frågor med O(p)-komplexitet.
Implementering av autocomplete med begränsat antal resultat
I produktionssystem för autocomplete är det opraktiskt att returnera alla ord med ett visst prefix när tusentals ord matchar. Använd i stället en max-heap med storleken k under DFS-genomgången: håll reda på de k ord med högst poäng som hittats hittills. Avsluta DFS-grenar tidigt om de omöjligen kan innehålla ett ord bland de k bästa (beskärning utifrån en övre gräns för poängen). Då blir tidskomplexiteten O(p + k × log k) per fråga för k förslag — mycket bättre än att samla in alla träffar.
Snabbkontroll
Testa dina kunskaper om koncepten i Data Structures & Algorithms — Coding Interview Prep från den här lektionen.
Sammanfattning av lektionen
I den här lektionen lärde du dig: starts_with går igenom prefixvägen och returnerar True om den finns — någon is_end-kontroll behövs inte, autocomplete-DFS samlar in alla ord från prefixets slutnod genom att lägga till tecken när den går nedåt, och att utöka noder med antal eller värden möjliggör summationsfrågor och top-k-förslag. Nästa steg är att lägga till matchning med jokertecken och reguljära uttryck i trien.
Lär dig Python med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 30
- Lektioner
- 120
Vanliga frågor
Är lektionen ”Prefixsökning och Starts-With” gratis?
Ja – du kan läsa vilka 3 lektioner som helst i lärvägen DSA Interview Prep, inklusive ”Prefixsökning och Starts-With”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i DSA Interview Prep innehåller totalt 4 lektioner.
Vad lär jag mig i ”Prefixsökning och Starts-With”?
Lägg till en starts_with-metod som returnerar true om något infogat ord delar ett angivet prefix och använd den för att implementera förslag på automatisk komplettering. Ni övar på DSA Interview Prep med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig DSA Interview Prep?
Du behöver inga förkunskaper. Utbildningen i DSA Interview Prep på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 2 av 4.
Hur lång tid tar lektionen ”Prefixsökning och Starts-With”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här DSA Interview Prep-lektionen?
Ja. Varje DSA Interview Prep-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- TrieNode-klassen: infogning och sökning
- Prefixsökning och Starts-With
- Wildcard- och regexsökning i ett trie
- Word Search II: trie och backtracking i ett rutnät