返回

LeetCode Java实现魔法字典题解:兼顾高效性和灵活性

后端

魔法字典:在 Java 中实现高效查找、插入和删除

简介

在现实世界的应用程序中,我们经常需要快速存储和查找单词。想象一下一个自动更正系统或拼写检查器,它需要能够快速查找单词是否存在,或者将单词插入或删除。在本文中,我们将探讨一种称为“魔法字典”的数据结构,它可以以 O(1) 的平均时间复杂度实现这些操作。

Trie:魔法字典背后的动力

魔法字典的核心是 Trie,也称为前缀树。Trie 是一种树形数据结构,它利用了单词的前缀来高效地存储和检索单词。每个 Trie 节点代表一个字符,而从根节点到叶节点的路径表示一个单词。

实现魔法字典

class MagicDictionary {
    private TrieNode root;

    // 初始化字典
    public MagicDictionary() {
        root = new TrieNode();
    }

    // 将单词插入字典
    public void insert(String word) {
        TrieNode cur = root;
        for (char c : word.toCharArray()) {
            int index = c - 'a';
            if (cur.children[index] == null) {
                cur.children[index] = new TrieNode();
            }
            cur = cur.children[index];
        }
        cur.isEnd = true;
    }

    // 删除单词
    public void delete(String word) {
        TrieNode cur = root;
        for (char c : word.toCharArray()) {
            int index = c - 'a';
            if (cur.children[index] == null) {
                return;
            }
            cur = cur.children[index];
        }
        cur.isEnd = false;
    }

    // 搜索单词
    public boolean search(String word) {
        return search(root, word, 0, false);
    }

    // 递归搜索单词
    private boolean search(TrieNode node, String word, int index, boolean hasDiff) {
        if (index == word.length()) {
            return node.isEnd && hasDiff;
        }

        char c = word.charAt(index);
        TrieNode next = node.children[c - 'a'];
        if (next != null) {
            if (search(next, word, index + 1, hasDiff)) {
                return true;
            }
            if (!hasDiff && next.isEnd) {
                return true;
            }
            return search(next, word, index + 1, true);
        }
        return false;
    }

    // Trie 节点
    class TrieNode {
        boolean isEnd;
        TrieNode[] children;

        public TrieNode() {
            isEnd = false;
            children = new TrieNode[26];
        }
    }
}

查找、插入和删除操作

使用 Trie,我们可以实现 O(1) 平均时间复杂度的查找、插入和删除操作。

  • 查找 (search) :搜索操作会遍历单词的字符,并在 Trie 中查找每个字符。如果找到一个与给定单词不同的单词,则设置hasDiff标志为true。如果找到一个完全匹配的单词,并且hasDifffalse,则返回true

  • 插入 (insert) :插入操作遍历单词的字符,并为每个字符创建相应的 Trie 节点。当到达单词末尾时,将isEnd标志设置为true,表示单词已经存储。

  • 删除 (delete) :删除操作类似于搜索,但是当到达单词末尾时,它会将isEnd标志设置为false

示例用法

MagicDictionary dictionary = new MagicDictionary();

// 插入单词
dictionary.insert("hello");
dictionary.insert("world");

// 搜索单词
System.out.println(dictionary.search("hello")); // true
System.out.println(dictionary.search("world")); // true
System.out.println(dictionary.search("helloworld")); // false

// 删除单词
dictionary.delete("hello");

// 再次搜索单词
System.out.println(dictionary.search("hello")); // false

优点

  • O(1) 平均时间复杂度用于查找、插入和删除操作
  • 存储单词和查询单词都非常高效
  • 轻松处理大型数据集
  • 非常适合实现自动更正和拼写检查器等应用程序

结论

魔法字典是一种强大的数据结构,它通过利用 Trie 的强大功能,实现了快速而高效的单词查找、插入和删除操作。对于需要处理大量单词并在 O(1) 时间内执行这些操作的应用程序来说,它是理想的选择。

常见问题解答

  1. 魔法字典与哈希表有何不同?

    哈希表是另一种高效的数据结构,它通过使用散列函数将键映射到值。然而,魔法字典专门用于存储和操作单词,并提供了额外的功能,例如搜索相似单词。

  2. 魔法字典是否可以存储重复的单词?

    不,魔法字典不存储重复的单词。如果插入一个已经存在的单词,它将覆盖现有单词。

  3. 魔法字典如何处理大小写?

    魔法字典通常不区分大小写。在插入和搜索单词时,它们通常被转换为小写。

  4. 魔法字典可以存储非英语单词吗?

    是的,魔法字典可以存储任何语言的单词,只要它们由字母组成。

  5. 魔法字典是否适合存储大量单词?

    是的,魔法字典非常适合存储大量单词。它具有 O(n) 的空间复杂度,其中 n 是字典中存储的单词数。