LeetCode 208 – 实现 Trie (前缀树)

题目描述

Trie(发音类似 “try”)或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补全和拼写检查。

请你实现 Trie 类:

Trie() 初始化前缀树对象。
void insert(String word) 向前缀树中插入字符串 word 。
boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false 。
boolean startsWith(String prefix) 如果之前已经插入的字符串 word 的前缀之一为 prefix ,返回 true ;否则,返回 false 。

题目分析

前缀树每个结点是一个字符,结点内有结束标记(表示有单词在这里结束),同时可以指向后续其他字符。复用的是从根结点出发的路径,而不是字符。
从根结点出发,字符串增加和查找的时间复杂度为 O(字符串长度)。
例如:
1. 插入hello:root → h → e → l → l → o (结束)
2. 插入help:root → h → e → l 是共享的,在 l 之后分叉出新分支 p(结束)

Java

public class Trie {

    private static class Node {

        public char ch;
        public boolean isEnd = false;
        private HashMap<Character, Node> next = new HashMap<>();

        public Node(char ch) {
            this.ch = ch;
        }

        private Node findNext(char ch) {
            return next.get(ch);
        }

        private Node addNext(char ch) {
            if (next.containsKey(ch)) {
                return next.get(ch);
            }
            Node node = new Node(ch);
            next.put(ch, node);
            return node;
        }

    }

    private Node root = new Node('0');

    public Trie() {

    }

    public void insert(String word) {
        Node cur = root;
        for (int i = 0; i < word.length(); i++) {
            cur = cur.addNext(word.charAt(i));
        }
        cur.isEnd = true;
    }

    public boolean search(String word) {
        Node cur = root;
        for (int i = 0; i < word.length(); i++) {
            cur = cur.findNext(word.charAt(i));
            if (cur == null) {
                return false;
            }
        }
        return cur.isEnd;
    }

    public boolean startsWith(String prefix) {
        Node cur = root;
        for (int i = 0; i < prefix.length(); i++) {
            cur = cur.findNext(prefix.charAt(i));
            if (cur == null) {
                return false;
            }
        }
        return true;
    }
}

Kotlin

class Trie {

    private class Node(val ch: Char, var isEnd: Boolean = false) {
        val next = HashMap<Char, Node>()

        fun addNext(ch: Char): Node {
            return findNext(ch) ?: Node(ch).also {
                next[ch] = it
            }
        }

        fun findNext(ch: Char): Node? {
            return next[ch]
        }
    }

    private val root = Node('0')


    fun insert(word: String) {
        var cur = root
        for (ch in word) {
            cur = cur.addNext(ch)
        }
        cur.isEnd = true
    }

    fun search(word: String): Boolean {
        var cur = root
        for (ch in word) {
            cur = cur.findNext(ch) ?: return false
        }
        return cur.isEnd
    }

    fun startsWith(prefix: String): Boolean {
        var cur = root
        for (ch in prefix) {
            cur = cur.findNext(ch) ?: return false
        }
        return true
    }
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部