Trie Tree(一)(字典樹)

Trie 樹,字典樹拇囊,try樹迂曲。

  • Trie 根節(jié)點(diǎn)不存在字符。
  • 從根節(jié)點(diǎn)開始寂拆,每個節(jié)點(diǎn)都是一個字符奢米,通過路徑連接起來。

可以用數(shù)組纠永,HashMap,和指針動態(tài)分配谒拴。
優(yōu)勢:時間復(fù)雜度低尝江。插入和查詢都是O(L),L為字符串長度英上。

敲黑板L啃颉!苍日!這里我跪過惭聂。

["world", "work", "see", "sold", "maven"] 的 Trie tree 表示如下:

trieTree.png

TrieNode定義(可根據(jù)情境更改定義):

/**
 * TrieNode definition.
 */
class TrieNode {
    boolean isLeaf;
    Map<Character, TrieNode> children; // use Map.

    public TrieNode() {
        this.isLeaf = false;           // init false.
        children = new HashMap<>();    // don't forget it.
    }
}

/**
 * Another definition of Trie.
 */
class TrieNode {
    int count;
    char ch;
    TrieNode children;

    public TrieNode() {
        count = 1;
        children = new TrieNode[26];    // 插入和查找時間復(fù)雜度O(1)
    }
}
/**
 * Insert. 
 * Use definition one(containing Map).
 */
 public void insert(TrieNode node, String str) {
    if (str == null || str.length() == 0) {
        return;
    }
    for (int i = 0; i < str.length(); i++) {
        char ch = str.charAt(i);
        if (node.children.containsKey(ch)) {    // 如果查找到,則繼續(xù)向下查找相恃。
            node = node.children.get(ch);
        } else {                                // 未查找到辜纲,則生成新節(jié)點(diǎn)。
            TrieNode child = new TrieNode();
            node.children.put(ch, child);
        }
    }
    node.isLeaf = true;  // after for-loop, set leaf true.
 }

/**
 * Trie Tree
 * Search
 */
public boolean search(TrieNode node, String str) {
    if (str == null || str.isEmpty()) {
        return false;
    }
    for (int i = 0; i < str.length(); i++) {
        char ch = str.charAt(i);
        if (!node.children.containsKey(ch)) {
            return false;
        } else {
            node = node.children.get(ch);
        }
    }
    return node.isLeaf == true;
}

Trie樹應(yīng)用:
字符串最左前綴匹配;
word search.

例子:[LeetCode-212]. Word Search II

一個由小寫字母組成的矩陣和一個字典耕腾,找出所有同時在字典和矩陣中出現(xiàn)的單詞见剩。
矩陣:
d o a f
a g a i
d c a n
字典:{"dog", "dad", "dgdg", "can", "again"}
返回結(jié)果:{"dog", "dad", "can", "again"}。

Word Search II 分析

對字典建立Trie 樹;
對矩陣每個元素進(jìn)行遍歷(2次for循環(huán))扫俺,然后DFS搜索苍苞。查找矩陣中是否存在字典中的字符串。
在DFS中狼纬,對于已經(jīng)遍歷過的字符羹呵,要進(jìn)行標(biāo)記×屏穑可以先存在temp變量中冈欢,然后標(biāo)記為“*”,DFS返回的時候再取回temp中的值没炒。

/**
 *  TrieNode
 */
class TrieNode {
    boolean isLeaf;
    Map<Character, TrieNode> children;

    public TrieNode() {
        isLeaf = false;
        children = new HashMap<>();
    }
}

/**
 *  TrieTree class.
 */
public class TrieTree {
    private TrieNode root;         // root node.

    public TrieTree() {
        root = new TrieNode();
    }

    public TrieNode getRoot() {    // return root node.
        return root;
    }
    
    // To insert a String list into Trie Tree.
    public void insertAll(List<String> list) {
        if (list == null || list.size() == 0) {
            return;
        }
        for (String str : list) {
            insertString(str);
        }
    }

    // To insert a String into Trie Tree.
    public void insertString(Stirng str) {
        if (str == null || str.isEmpty()) {
            return;
        }
        TrieNode node = root;    // to get reference of root.
        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            if (!node.children.containsKey(ch)) {
                TrieNode child = new TrieNode();
                node.children.put(ch, child);
            }
            node = node.children.get(ch);  // if containing ch.
        }
        node.isLeaf = true;
    }

}
/**
 *  Search word, using DFS.
 */
public class WordSearch {
    
    public List<String> findWords(char[][] board, List<String> words) {
        if (words == null || words.size() == 0) {
            return new ArrayList<String>();
        }
        if (board.length == 0 || board[0].length == 0) {
            return new ArrayList<String>();
        }
        Set<String> resSet = new HashSet<String>();
        TrieTree trieTree = new TrieTree();
        TrieNode root = trieTree.getRoot();
         
        int m = board.length;
        int n = board[0].length;
        for (int i = 0; i < m; i++) {    // 兩次for循環(huán)遍歷二維數(shù)組涛癌。
            for (int j = 0; j < n; j++) {
                dfs(board, TrieNode root, resSet, "", i, j);    // DFS搜索
            }
        }
        return new ArrayList<String>(resSet);
    }

    /**
     * DFS
     */
    private void dfs(char[][] board, TrieNode root, Set<String> resSet, String word, int i, int j) {
        if (i < 0 || j < 0 || i >= board.length || j >= board[0].length || board[i][j] == '*') {
            return;
        }
        if (root.children.containsKey(board[i][j])) {
            word += board[i][j];
            root = root.children.get(board[i][j]);
            if (root.isLeaf) {    // 查找到葉子節(jié)點(diǎn),添加結(jié)果
                resSet.add(word);
            }
            char tmp = board[i][j];
            board[i][j] = '*';    // 標(biāo)記為已訪問
            dfs(board, root, resSet, word, i + 1, j);
            dfs(board, root, resSet, word, i - 1, j);
            dfs(board, root, resSet, word, i, j + 1);
            dfs(board, root, resSet, word, i, j - 1);
            board[i][j] = tmp;    // 復(fù)原已訪問中的元素
        }
        return;
    }

}

更多應(yīng)用舉例:Trie Tree(二):Maximum XOR of Two Number in an Array?

[已完結(jié)]

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末送火,一起剝皮案震驚了整個濱河市拳话,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌种吸,老刑警劉巖弃衍,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異坚俗,居然都是意外死亡镜盯,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門猖败,熙熙樓的掌柜王于貴愁眉苦臉地迎上來速缆,“玉大人,你說我怎么就攤上這事恩闻∫彰樱” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵幢尚,是天一觀的道長破停。 經(jīng)常有香客問我,道長尉剩,這世上最難降的妖魔是什么真慢? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮理茎,結(jié)果婚禮上黑界,老公的妹妹穿的比我還像新娘管嬉。我一直安慰自己,他們只是感情好园爷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布宠蚂。 她就那樣靜靜地躺著,像睡著了一般童社。 火紅的嫁衣襯著肌膚如雪求厕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天扰楼,我揣著相機(jī)與錄音呀癣,去河邊找鬼。 笑死弦赖,一個胖子當(dāng)著我的面吹牛项栏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蹬竖,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼沼沈,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了币厕?” 一聲冷哼從身側(cè)響起列另,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎旦装,沒想到半個月后页衙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡阴绢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年店乐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呻袭。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡眨八,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出左电,到底是詐尸還是另有隱情踪古,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布券腔,位于F島的核電站,受9級特大地震影響拘泞,放射性物質(zhì)發(fā)生泄漏纷纫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一陪腌、第九天 我趴在偏房一處隱蔽的房頂上張望辱魁。 院中可真熱鬧烟瞧,春花似錦、人聲如沸染簇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锻弓。三九已至砾赔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間青灼,已是汗流浹背暴心。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留杂拨,地道東北人专普。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像弹沽,于是被迫代替她去往敵國和親檀夹。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問題, 分享了一些自己做題目的經(jīng)驗(yàn)策橘。 張土汪:刷leetcod...
    土汪閱讀 12,743評論 0 33
  • (本文轉(zhuǎn)自百度搜索第一個CSDN博客) 一炸渡、知識簡介 Trie 的強(qiáng)大之處就在于它的時間復(fù)雜度。它的插入和查詢時間...
    Alan66閱讀 827評論 0 0
  • LeetCode 刷題隨手記 - 第一部分 前 256 題(非會員)役纹,僅算法題偶摔,的吐槽 https://leetc...
    蕾娜漢默閱讀 17,764評論 2 36
  • 文字/ 徐丹妮 圖片 / 陳曦 大多數(shù)人兒時都有個夢想:環(huán)游世界瘸味。 隨著年齡的增長宫仗,我們漸漸意識到這是件困難的...
    徐丹妮閱讀 2,194評論 22 49
  • 春天, 被一只蝴蝶帶到天空旁仿,交給流動的云藕夫。 花瓣從枝椏中悄悄伸出舌頭,去舔太陽的光枯冈。 不經(jīng)意打開車窗毅贮, 擦過去的風(fēng)...
    由之FLORA閱讀 521評論 2 1