Java實(shí)現(xiàn)前綴樹詳解
一.前綴樹
1.什么是前綴樹
字典樹(Trie樹)是一種樹形數(shù)據(jù)結(jié)構(gòu),常用于字符串的存儲和查找。字典樹的核心思想是利用字符串之間的公共前綴來節(jié)省存儲空間和提高查詢效率。它是一棵多叉樹,每個節(jié)點(diǎn)代表一個字符串的前綴,從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑組成一個字符串。
字典樹的根節(jié)點(diǎn)不包含字符,每個子節(jié)點(diǎn)代表一個字符,從根節(jié)點(diǎn)到任意一個節(jié)點(diǎn)所經(jīng)過的路徑上的字符連接起來即為該節(jié)點(diǎn)所代表的字符串。每個節(jié)點(diǎn)可以存儲一個或多個字符串,通常使用一個標(biāo)志來標(biāo)記一個節(jié)點(diǎn)代表的字符串是否存在。當(dāng)需要在一組字符串中查找某個字符串時,可以利用字典樹來實(shí)現(xiàn)高效的查找操作。
2.前綴樹的舉例
例如對字符串?dāng)?shù)組{"goog","google","bai","baidu","a"}建立前綴樹,此時我們可以很清晰的看到前綴樹的一些特征:
- 根結(jié)點(diǎn)不保存字符
- 前綴樹是一顆多叉樹
- 前綴樹的每個節(jié)點(diǎn)保存一個字符
- 具有相同前綴的字符串保存在同一條路徑上
- 字符串的尾處相應(yīng)的在前綴樹上也有結(jié)束的標(biāo)志

二.前綴樹的實(shí)現(xiàn)
力扣上的208題就是實(shí)現(xiàn)前綴樹:力扣
1.前綴樹的數(shù)據(jù)結(jié)構(gòu)
在寫代碼的時候,我偏向于用哈希表來存儲結(jié)點(diǎn)的信息,有的也可以用數(shù)組來存儲結(jié)點(diǎn)的信息,本質(zhì)上都是一樣的
public class Trie {
Map<Character, Trie> next;
boolean isEnd;
public Trie() {
this.next = new HashMap<>();
this.isEnd = false;
}
public void insert(String word) {
}
public boolean search(String word) {
return false;
}
public boolean startsWith(String prefix) {
return false;
}
}2.插入字符串
public void insert(String word) {
Trie trie = this;//獲得根結(jié)點(diǎn)
for (char c : word.toCharArray()) {
if (trie.next.get(c) == null) {//當(dāng)前結(jié)點(diǎn)不存在
trie.next.put(c, new Trie());//創(chuàng)建當(dāng)前結(jié)點(diǎn)
}
trie = trie.next.get(c);//得到字符c的結(jié)點(diǎn),繼續(xù)向下遍歷
}
trie.isEnd = true;
}3.查找字符串
public boolean search(String word) {
Trie trie = this;//獲得根結(jié)點(diǎn)
for (char c : word.toCharArray()) {
if (trie.next.get(c) == null) {//當(dāng)前結(jié)點(diǎn)不存在
return false;
}
trie = trie.next.get(c);//得到字符c的結(jié)點(diǎn),繼續(xù)向下遍歷
}
return trie.isEnd;
}4.查找前綴
public boolean startsWith(String prefix) {
Trie trie = this;//獲得根結(jié)點(diǎn)
for (char c : prefix.toCharArray()) {
if (trie.next.get(c) == null) {//當(dāng)前結(jié)點(diǎn)不存在
return false;
}
trie = trie.next.get(c);//得到字符c的結(jié)點(diǎn),繼續(xù)向下遍歷
}
return true;
}接下來是力扣上關(guān)于前綴樹的一些題目
三.詞典中最長的單詞
1.題目描述
給出一個字符串?dāng)?shù)組words 組成的一本英語詞典。返回words 中最長的一個單詞,該單詞是由words詞典中其他單詞逐步添加一個字母組成。
若其中有多個可行的答案,則返回答案中字典序最小的單詞。若無答案,則返回空字符串。
力扣:力扣
2.問題分析
這是一道典型的前綴樹的問題,但是這一題有一些特殊的要求,返回的答案是:
1.最長的單詞
2.這個單詞由其他單詞逐步構(gòu)成
3.長度相同返回字典序小的
因此我們需要對前綴樹的相關(guān)代碼進(jìn)行修改,把字符串一一插入的代碼還是不改變的,主要修改的是查找的代碼,應(yīng)該在 trie.next.get(c) == null在增加一個判斷為false的條件,就是每一個結(jié)點(diǎn)都應(yīng)該有一個標(biāo)志true,表示每個節(jié)點(diǎn)都存在一個單詞,最終一步步構(gòu)成最長的單詞(葉子結(jié)點(diǎn)的單詞)
3.代碼實(shí)現(xiàn)
class Solution {
public String longestWord(String[] words) {
Trie trie = new Trie();
for (String word : words) {
trie.insert(word);
}
String longest = "";
for (String word : words) {
if (trie.search(word)) {
if (word.length() > longest.length() || ((word.length() == longest.length()) && (word.compareTo(longest) < 0))) {
longest = word;
}
}
}
return longest;
}
}
class Trie {
Map<Character, Trie> next;
boolean isEnd;
public Trie() {
this.next = new HashMap<>();
this.isEnd = false;
}
public void insert(String word) {
Trie trie = this;//獲得根結(jié)點(diǎn)
for (char c : word.toCharArray()) {
if (trie.next.get(c) == null) {//當(dāng)前結(jié)點(diǎn)不存在
trie.next.put(c, new Trie());//創(chuàng)建當(dāng)前結(jié)點(diǎn)
}
trie = trie.next.get(c);//得到字符c的結(jié)點(diǎn),繼續(xù)向下遍歷
}
trie.isEnd = true;
}
public boolean search(String word) {
Trie trie = this;//獲得根結(jié)點(diǎn)
for (char c : word.toCharArray()) {
if (trie.next.get(c) == null || !trie.next.get(c).isEnd) {//當(dāng)前結(jié)點(diǎn)不存在
return false;
}
trie = trie.next.get(c);//得到字符c的結(jié)點(diǎn),繼續(xù)向下遍歷
}
return trie.isEnd;
}
}
到此這篇關(guān)于Java實(shí)現(xiàn)前綴樹詳解的文章就介紹到這了,更多相關(guān)Java前綴樹內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java基于websocket協(xié)議與netty實(shí)時視頻彈幕交互實(shí)現(xiàn)
本文主要介紹了Java基于websocket協(xié)議與netty實(shí)時視頻彈幕交互實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09
Elasticsearch?Recovery索引分片分配詳解
這篇文章主要為大家介紹了關(guān)于Elasticsearch的Recovery索引分片分配詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>2022-04-04
Spring大白話之三級緩存如何解決循環(huán)依賴問題
Spring通過三級緩存(singletonObjects、earlySingletonObjects、singletonFactories)解決單例循環(huán)依賴,三級緩存使用Lambda表達(dá)式提前暴露bean的早期引用,確保在遞歸調(diào)用時能夠正確獲取對象實(shí)例,避免死循環(huán)2025-02-02
Mybatis實(shí)現(xiàn)批量操作8種小結(jié)
本文對Mybatis的五種批處理方式進(jìn)行了性能測試,包括批量新增和批量修改,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-10-10
Java中==與equals()及hashcode()三者之間的關(guān)系詳解
最近也是在讀Hollis的《深入理解Java核心技術(shù)》里面一節(jié)講到了equals()和hashcode()的關(guān)系,對于這個高頻面試點(diǎn),咱們需要認(rèn)真理清一下幾者之間的關(guān)系2022-10-10

