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;
    }
}

 

你可能感兴趣的:(leetcode)