leetcode 實現 Trie (前綴樹) (單詞查找樹)

208. 實現 Trie (前綴樹)

題目描述

實現一個 Trie (前綴樹),包含 insertsearch, 和 startsWith 這三個操作。

示例:

Trie trie = new Trie();

trie.insert("apple");
trie.search("apple");   // 返回 true
trie.search("app");     // 返回 false
trie.startsWith("app"); // 返回 true
trie.insert("app");   
trie.search("app");     // 返回 true

說明:

  • 你可以假設所有的輸入都是由小寫字母 a-z 構成的。
  • 保證所有輸入均爲非空字符串

第一種:R向單詞查找樹,每個節點都含有R個鏈接,對應着每個可能出現的字符,優點在於查找和插入的效率很高,與單詞的長度成正比。缺點是空間消耗大。

/**
 * @author yuan
 * @date 2019/1/23
 * @description R向單詞查找樹
 */
public class Trie {

    private Node root;
    private static int R = 26;
    private class Node{
        Node[] next = new Node[R];
        char c;
        boolean isWordEnd = false;
    }

    /** Initialize your data structure here. */
    public Trie() {
    }


    /** Inserts a word into the trie. */
    public void insert(String word) {
        root = insert(root, word, 0);
    }

    private Node insert(Node x, String word, int d) {
        if (x == null) {
            x = new Node();
        }
        if (d == word.length()) {
            x.isWordEnd = true;
            return x;
        }
        char c = word.charAt(d);
        x.next[c - 'a'] = insert(x.next[c - 'a'], word, d + 1);
        return x;
    }

    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        Node x = search(root, word, 0);
        if (x == null) {
            return false;
        }
        return x.isWordEnd;
    }

    private Node search(Node x, String word, int d) {
        if (x == null) {
            return null;
        }
        if (d == word.length()) {
            return x;
        }
        char c = word.charAt(d);
        return search(x.next[c - 'a'], word, d + 1);

    }

    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        Node x = search(root, prefix, 0);
        return x != null;
    }
}

第二種:三向單詞查找樹,每個節點只有3個鏈接,所需空間遠小於單詞查找樹。

三向單詞查找樹適用於查找鍵的不規則形。

比如有256個字符,R向單詞樹需要256向分支,需要巨大的開銷,而三向單詞查找樹就不必擔心這個問題。


/**
 * @author yuan
 * @date 2019/2/22
 * @description 三向單詞查找樹
 */
public class Trie {
    private Node root;

    private class Node{
        /**
         * 字符
         */
        char c;
        /**
         * 左中右子三向單詞查找樹
         */
        Node left,mid, right;
        boolean isWordEnd = false;
    }

    /** Initialize your data structure here. */
    public Trie() {
    }

    public boolean search(String word) {
        Node x = search(root, word, 0);
        if (x == null) {
            return false;
        }
        return x.isWordEnd;
    }

    private Node search(Node x, String word, int d) {
        if (x == null) {
            return null;
        }
        char c = word.charAt(d);
        if (c < x.c) {
            return search(x.left, word, d);
        } else if (c > x.c) {
            return search(x.right, word, d);
        } else if (d < word.length() - 1) {
            return search(x.mid, word, d + 1);
        }
        return x;
    }

    public void insert(String word) {
        root = insert(root, word, 0);
    }

    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        Node x = search(root, prefix, 0);
        return x != null;
    }



    private Node insert(Node x, String word, int d) {
        char c = word.charAt(d);
        if (x == null) {
            x = new Node();
            x.c = c;
        }
        if (c < x.c) {
            x.left = insert(x.left, word, d);
        } else if (c > x.c) {
            x.right = insert(x.right, word, d);
        } else if (d < word.length() - 1) {
            x.mid = insert(x.mid, word, d + 1);
        } else {
            // 此時d = word.length - 1,到了單詞的尾部
            x.isWordEnd = true;
        }
        return x;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章