「程序员必须掌握的算法」字典树「上篇」

简介: 「程序员必须掌握的算法」字典树「上篇」

「程序员必须掌握的算法」字典树「上篇」

前言: 在计算机科学中,字典树(Trie)是一种有序树,用于保存关联数组(有时我们称之为“映射”或“字典”)。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。字典树的优势在于能够非常快速地查找、插入和删除字符串。

本篇文章将介绍字典树的基本概念、构建方法以及应用场景,并通过三道例题由浅入深地说明字典树的应用。



基本概念

字典树是一种树形结构,典型应用是用于统计和排序大量的字符串(但不限于字符串)。它经常被搜索引擎系统用于文本词频统计。

以下是字典树的基本概念:

  • 根节点不包含字符,除根节点外每一个节点都只包含一个字符;
  • 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串;
  • 每个节点的所有子节点包含的字符都不相同。

构建方法

一个字典树的典型操作是插入一个字符串,我们可以按照以下步骤插入一个字符串:

  • 从根节点开始,找到第一个字符所在的节点;
  • 如果找到对应的节点,继续寻找下一个字符;
  • 如果找不到对应的节点,创建一个新节点,将其链接到前一个节点的对应指针上,并继续寻找下一个字符。

以下是Java代码实现:

class TrieNode {
    public boolean isWord;
    public TrieNode[] children = new TrieNode[26];
}
class Trie {
    private TrieNode root;
    public Trie() {
        root = new TrieNode();
    }
    /** Inserts a word into the trie. */
    public void insert(String word) {
        TrieNode node = root;
        for (char c : word.toCharArray()) {
            if (node.children[c - 'a'] == null) {
                node.children[c - 'a'] = new TrieNode();
            }
            node = node.children[c - 'a'];
        }
        node.isWord = true;
    }
    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        TrieNode node = root;
        for (char c : word.toCharArray()) {
            if (node.children[c - 'a'] == null) {
                return false;
            }
            node = node.children[c - 'a'];
        }
        return node.isWord;
    }
    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        TrieNode node = root;
        for (char c : prefix.toCharArray()) {
            if (node.children[c - 'a'] == null) {
                return false;
            }
            node = node.children[c - 'a'];
        }
        return true;
    }
}

应用场景

字典树最常见的应用场景是字符串相关的问题,以下是三道例题由浅入深地说明字典树的应用:

例题一:查找单词

给定一个单词集合(如下所示),查找一个单词是否在集合中出现。

["hello", "world", "leetcode"]

以下是Java代码实现:

class Solution {
    public boolean findWord(String[] words, String target) {
        Trie trie = new Trie();
        for (String word : words) {
            trie.insert(word);
        }
        return trie.search(target);
    }
}

例题二:查找单词前缀

给定一个单词集合(如下所示),查找一个单词是否是集合中的某个单词的前缀。

["hello", "world", "leetcode"]

以下是Java代码实现:

class Solution {
    public boolean findPrefix(String[] words, String target) {
        Trie trie = new Trie();
        for (String word : words) {
            trie.insert(word);
        }
        return trie.startsWith(target);
    }
}

例题三:计算单词前缀数量

给定一个单词集合(如下所示),计算以某个前缀开头的单词数量。

["hello", "world", "leetcode"]

以下是Java代码实现:

class TrieNode {
    public int count;
    public TrieNode[] children = new TrieNode[26];
}
class Trie {
    private TrieNode root;
    public Trie() {
        root = new TrieNode();
    }
    public void insert(String word) {
        TrieNode node = root;
        for (char c : word.toCharArray()) {
            if (node.children[c - 'a'] == null) {
                node.children[c - 'a'] = new TrieNode();
            }
            node = node.children[c - 'a'];
            node.count++;
        }
    }
    public int countPrefix(String prefix) {
        TrieNode node = root;
        for (char c : prefix.toCharArray()) {
            if (node.children[c - 'a'] == null) {
                return 0;
            }
            node = node.children[c - 'a'];
        }
        return node.count;
    }
}
class Solution {
    public int countPrefix(String[] words, String prefix) {
        Trie trie = new Trie();
        for (String word : words) {
            trie.insert(word);
        }
        return trie.countPrefix(prefix);
    }
}

在上述代码中,我们通过 countPrefix 方法来计算以某个前缀开头的单词数量。

总结

本篇文章介绍了字典树的基本概念、构建方法和应用场景,并提供了三道例题由浅入深地说明字典树的应用。在实际开发中,字典树是一种非常常用的数据结构,能够帮助我们解决各种字符串相关的问题。

相关文章
|
2月前
|
负载均衡 监控 算法
每个程序员都应该知道的 6 种负载均衡算法
每个程序员都应该知道的 6 种负载均衡算法
226 2
|
3月前
|
算法 程序员 Python
程序员必看!Python复杂度分析全攻略,让你的算法设计既快又省内存!
在编程领域,Python以简洁的语法和强大的库支持成为众多程序员的首选语言。然而,性能优化仍是挑战。本文将带你深入了解Python算法的复杂度分析,从时间与空间复杂度入手,分享四大最佳实践:选择合适算法、优化实现、利用Python特性减少空间消耗及定期评估调整,助你写出高效且节省内存的代码,轻松应对各种编程挑战。
60 1
|
4月前
|
算法 搜索推荐 程序员
程序员常用算法详细讲解
每一种算法都有其适用场景,了解并熟悉这些常用算法的策略和实现,对于解决实际编程问题具有重要的意义。需要注意的是,理论知识的重要性虽然不言而喻,但真正的理解和掌握,还需要在实践中不断地尝试和错误,以达到深入理解的目的。
41 1
|
4月前
|
机器学习/深度学习 算法 搜索推荐
程序员必须掌握的算法
作为一名程序员,掌握一些重要的算法是必不可少的。算法是解决问题的方法和步骤,对于程序员来说,熟悉和掌握一些常见的算法可以提高编程能力,解决复杂的计算问题。与此同时,算法是计算机科学中的核心概念,对于程序员来说,掌握一些基本的算法是非常重要的。
53 1
|
6月前
|
算法 程序员
程序员必知:XGB算法梳理
程序员必知:XGB算法梳理
34 0
|
6月前
|
算法 JavaScript 程序员
程序员必知:《程序设计与算法(二)算法基础》《第一周枚举》熄灯问题POJ
程序员必知:《程序设计与算法(二)算法基础》《第一周枚举》熄灯问题POJ
35 0
|
18天前
|
算法
基于WOA算法的SVDD参数寻优matlab仿真
该程序利用鲸鱼优化算法(WOA)对支持向量数据描述(SVDD)模型的参数进行优化,以提高数据分类的准确性。通过MATLAB2022A实现,展示了不同信噪比(SNR)下模型的分类误差。WOA通过模拟鲸鱼捕食行为,动态调整SVDD参数,如惩罚因子C和核函数参数γ,以寻找最优参数组合,增强模型的鲁棒性和泛化能力。
|
24天前
|
机器学习/深度学习 算法 Serverless
基于WOA-SVM的乳腺癌数据分类识别算法matlab仿真,对比BP神经网络和SVM
本项目利用鲸鱼优化算法(WOA)优化支持向量机(SVM)参数,针对乳腺癌早期诊断问题,通过MATLAB 2022a实现。核心代码包括参数初始化、目标函数计算、位置更新等步骤,并附有详细中文注释及操作视频。实验结果显示,WOA-SVM在提高分类精度和泛化能力方面表现出色,为乳腺癌的早期诊断提供了有效的技术支持。
|
4天前
|
供应链 算法 调度
排队算法的matlab仿真,带GUI界面
该程序使用MATLAB 2022A版本实现排队算法的仿真,并带有GUI界面。程序支持单队列单服务台、单队列多服务台和多队列多服务台三种排队方式。核心函数`func_mms2`通过模拟到达时间和服务时间,计算阻塞率和利用率。排队论研究系统中顾客和服务台的交互行为,广泛应用于通信网络、生产调度和服务行业等领域,旨在优化系统性能,减少等待时间,提高资源利用率。