力扣labuladong一刷day54天前缀树

力扣labuladong一刷day54天前缀树

文章目录

      • 力扣labuladong一刷day54天前缀树
      • 一、208. 实现 Trie (前缀树)
      • 二、648. 单词替换
      • 三、211. 添加与搜索单词 - 数据结构设计
      • 四、1804. 实现 Trie (前缀树) II
      • 五、677. 键值映射

一、208. 实现 Trie (前缀树)

题目链接:https://leetcode.cn/problems/implement-trie-prefix-tree/description/?utm_source=LCUS&utm_medium=ip_redirect&utm_campaign=transfer2china
思路:类似于下图就是前缀树,本质是多叉树,只不过表示子节点的数组是通过字母进行索引的,叶子节点有值来表示。
在这里插入图片描述

class Trie {

    Node root = null;
    class Node{
        int v = 0;
        Node[] child = new Node[26];
    }
    public Trie() {

    }

    public void insert(String word) {
        if (search(word)) {
            return;
        }
        root = addNode(root, word, 0);
    }

    public boolean search(String word) {
        Node node = getNode(root, word);
        if (node == null || node.v == 0) {
            return false;
        }
        return true;
    }

    public boolean startsWith(String prefix) {
        return getNode(root, prefix) != null;
    }

    Node getNode(Node node, String word) {
        Node p = node;
        for (int i = 0; i < word.length(); i++) {
            if (p == null) {
                return null;
            }
            p = p.child[word.charAt(i)-'a'];
        }
        return p;
    }

    Node addNode(Node node, String word, int i) {
        if (node == null) {
            node = new Node();
        }
        if (i == word.length()) {
            node.v = 1;
            return node;
        }
        int c = word.charAt(i) - 'a';
        node.child[c] = addNode(node.child[c], word, i+1);
        return node;
    }
}

/**
 * Your Trie object will be instantiated and called as such:
 * Trie obj = new Trie();
 * obj.insert(word);
 * boolean param_2 = obj.search(word);
 * boolean param_3 = obj.startsWith(prefix);
 */

二、648. 单词替换

题目链接:https://leetcode.cn/problems/replace-words/description/?utm_source=LCUS&utm_medium=ip_redirect&utm_campaign=transfer2china
思路:和上题一样,也是前缀树的应用,只不过多了一个最短前缀替换。

class Solution {
    public String replaceWords(List<String> dictionary, String sentence) {
        Trie trie = new Trie();
        for (String s : dictionary) {
            trie.insert(s);
        }
        String[] split = sentence.split(" ");
        StringBuilder bf = new StringBuilder();
        for (String s : split) {
            String ms = trie.minSearch(s);
            if ("".equals(ms)) {
                bf.append(s);
            }else {
                bf.append(ms);
            }
            bf.append(" ");
        }
        bf.deleteCharAt(bf.length()-1);
        return bf.toString();
    }

    class Node {
        int v = 0;
        Node[] child = new Node[26];
    }
    class Trie {
        Node root = null;

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

        String minSearch(String word) {
            Node p = root;
            for (int i = 0; i < word.length(); i++) {
                if (p == null) return "";
                if (p.v == 1) {
                    return word.substring(0, i);
                }
                p = p.child[word.charAt(i)-'a'];
            }
            if (p != null && p.v == 1) return word;
            return "";
        }

        boolean search(String word) {
            Node node = getNode(word);
            if (node == null || node.v == 0) return false;
            return true;
        }

        Node getNode(String word) {
            Node p = root;
            for (int i = 0; i < word.length(); i++) {
                if (p == null) return null;
                p = p.child[word.charAt(i)-'a'];
            }
            return p;
        }

        Node addNode(Node node, String word, int i) {
            if (node == null) {
                node = new Node();
            }
            if (i == word.length()) {
                node.v = 1;
                return node;
            }
            int c = word.charAt(i)-'a';
            node.child[c] = addNode(node.child[c], word, i+1);
            return node;
        }
    }
}

三、211. 添加与搜索单词 - 数据结构设计

题目链接:https://leetcode.cn/problems/design-add-and-search-words-data-structure/description/
思路:本题还是前缀树,和上一题类似,唯一不同的点是多了一个模式串匹配。

class WordDictionary {
    Node root = null;
    public WordDictionary() {

    }

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

    public boolean search(String word) {
        return traverse(root, word, 0);
    }

    boolean traverse(Node node, String word, int i) {
        if (node == null) return false;
        if (i == word.length()) {
            return node.v == 1;
        }
        if ('.' == word.charAt(i)) {
            for (int j = 0; j < 26; j++) {
                boolean flag = traverse(node.child[j], word, i + 1);
                if (flag) return flag;
            }
        }else {
            return traverse(node.child[word.charAt(i)-'a'], word, i+1);
        }
        return false;
    }

    Node addNode(Node node, String word, int i) {
        if (node == null) {
            node = new Node();
        }
        if (i == word.length()) {
            node.v = 1;
            return node;
        }
        int c = word.charAt(i)-'a';
        node.child[c] = addNode(node.child[c], word, i+1);
        return node;
    }

}
class Node {
    int v;
    Node[] child = new Node[26];
}

/**
 * Your WordDictionary object will be instantiated and called as such:
 * WordDictionary obj = new WordDictionary();
 * obj.addWord(word);
 * boolean param_2 = obj.search(word);
 */

四、1804. 实现 Trie (前缀树) II

题目链接:https://leetcode.cn/problems/implement-trie-ii-prefix-tree/description/?utm_source=LCUS&utm_medium=ip_redirect&utm_campaign=transfer2china
思路:本题的前缀树多增加了一个功能就是删除节点,删除节点要考虑的就比较多了,到达value的位置要把数量减一,然后在后序位置删除,如果值大于0直接返回就行,不用删除节点,如果值不大于0就需要看该节点的child是否全为null,如果是返回Null就删除了,不是的话保留。

class Trie {
    Node root;
    public Trie() {

    }

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

    public int countWordsEqualTo(String word) {
        Node node = getNode(word);
        if (null == node) return 0;
        return node.v;
    }

    public int countWordsStartingWith(String prefix) {
        Node node = getNode(prefix);
        if (node == null) return 0;
        return traverse(node, 0);
    }

    public void erase(String word) {
        if (getNode(word) == null) return;
        root = deleteNode(root, word, 0);
    }
    Node deleteNode(Node node, String word, int i) {
        if (node == null) return null;
        if (i == word.length()) {
            if (node.v > 0) node.v--;
        }else {
            int c = word.charAt(i)-'a';
            node.child[c] = deleteNode(node.child[c], word, i+1);
        }
        if (node.v > 0) return node;
        for (int j = 0; j < 26; j++) {
            if (node.child[j] != null) {
                return node;
            }
        }
        return null;
    }
    int traverse(Node node, int num) {
        if (node == null) return 0;
        num = node.v;
        for (int i = 0; i < 26; i++) {
            num += traverse(node.child[i], num);
        }
        return num;
    }

    Node addNode(Node node, String word, int i) {
        if (node == null) {
            node = new Node();
        }
        if (i == word.length()) {
            node.v += 1;
            return node;
        }
        int c = word.charAt(i)-'a';
        node.child[c] = addNode(node.child[c], word, i+1);
        return node;
    }

    Node getNode(String word) {
        Node p = root;
        for (int i = 0; i < word.length(); i++) {
            if (p == null) return null;
            p = p.child[word.charAt(i)-'a'];
        }
        return p;
    }
}
class Node{
    int v = 0;
    Node[] child = new Node[26];
}

/**
 * Your Trie object will be instantiated and called as such:
 * Trie obj = new Trie();
 * obj.insert(word);
 * int param_2 = obj.countWordsEqualTo(word);
 * int param_3 = obj.countWordsStartingWith(prefix);
 * obj.erase(word);
 */

五、677. 键值映射

题目链接:https://leetcode.cn/problems/map-sum-pairs/description/?utm_source=LCUS&utm_medium=ip_redirect&utm_campaign=transfer2china
思路:关键点是前缀查询,先获取到前缀的节点,然后广度优先遍历,前序位置记录节点位置。

class MapSum {
    Node root = null;
    public MapSum() {

    }

    public void insert(String key, int val) {
        root = addNode(root, key, val, 0);
    }

    public int sum(String prefix) {
        Node node = getNode(prefix);
        if (node == null) return 0;
        return traverse(node, 0);
    }
    int traverse(Node node, int num) {
        if (node == null) return 0;
        num = node.v;
        for (int i = 0; i < 26; i++) {
            num += traverse(node.child[i], num);
        }
        return num;
    }
    

    Node getNode(String word) {
        Node p = root;
        for (int i = 0; i < word.length(); i++) {
            if (p == null) return null;
            p = p.child[word.charAt(i)-'a'];
        }
        return p;
    }
    Node addNode(Node node, String word, int value, int i) {
        if (node == null) {
            node = new Node();
        }
        if (i == word.length()) {
            node.v = value;
            return node;
        }
        int c = word.charAt(i) - 'a';
        node.child[c] = addNode(node.child[c], word, value, i+1);
        return node;
    }

}
class Node {
    int v = 0;
    Node[] child = new Node[26];
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/301604.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

解锁Mac的无限可能:Sensei for Mac - 你的全能系统优化清理助手

你是否经常为Mac的缓慢速度和不断积累的缓存文件而感到烦恼&#xff1f;不用担心&#xff0c;因为今天&#xff0c;我要向您介绍一款全新的系统优化清理工具 - Sensei for Mac。 作为一款卓越的系统清理工具&#xff0c;Sensei for Mac在保持您的Mac系统流畅运行的同时&#x…

2024--Django平台开发-Django知识点(三)

day03 django知识点 项目相关路由相关 urls.py视图相关 views.py模版相关 templates资源相关 static/media 1.项目相关 新项目 开发时&#xff0c;可能遇到使用其他的版本。虚拟环境 老项目 打开项目虚拟环境 1.1 关于新项目 1.系统解释器命令行【学习】 C:/python38- p…

【VSCode】CMake Language Support 总是下载 .NET 超时,但又不想升级dotnet

错误信息 Error: Could not resolve dotnet path!An error occurred while installing .NET (6.0): .NET Acquisition Failed: Installation failed: Error: .NET installation timed out. You may need to change the timeout time if you have a slow connection. Please se…

https配置证书

HTTPS 基本原理 https 介绍 HTTPS&#xff08;全称&#xff1a;HyperText Transfer Protocol over Secure Socket Layer&#xff09;&#xff0c;其实 HTTPS 并不是一个新鲜协议&#xff0c;Google 很早就开始启用了&#xff0c;初衷是为了保证数据安全。 国内外的大型互联网…

OpenAI ChatGPT-4开发笔记2024-05:windows下anaconda中设置visual studio code workspace

这里写自定义目录标题 1 安装anaconda和vscode2 Create an Anaconda Environment3 select Python Interpreter4 Workspace5 Open Workspace With File6 开发文件夹加入workspace7 美化 1 安装anaconda和vscode 标配。 2 Create an Anaconda Environment conda create --name…

编译原理Lab4-使用LightIR框架自动产生cminus-f语言的LLVM IR

[[#实验框架|实验框架]][[#实验过程|实验过程]] [[#实验过程#全局变量的设计|全局变量的设计]][[#实验过程#1ASTProgram|1ASTProgram]][[#实验过程#2ASTNum|2ASTNum]][[#实验过程#3ASTVarDeclaration|3ASTVarDeclaration]][[#实验过程#4ASTFunDeclaration|4ASTFunDeclaration]]…

简析云能耗管理系统在某高校建筑系统平台的设计与应用

叶根胜 安科瑞电气股份有限公司 上海嘉定 201801 摘要&#xff1a;根据本项目&#xff0c;依托某学院电能计量管理系统、供水计量监督系统、供热计量管理系统等基础平台&#xff0c;制定了高校建筑能耗综合管理系统平台应用的总体框架和方案。该系统可以实时监控、统计能耗和…

轻松掌握 Java Faker ,学点真本事,做点“假”数据~

工作中难免遇到需要造点“假”数据的情况&#xff0c;而且数据必须是“真”的&#xff0c;演示效果要好看一些。 一般接到这种要求&#xff0c;大部分的测试都不太知道该怎么去做。今天罗杰老师教你一招&#xff0c;让你做出逼真的“假”数据。 前言 1、什么是 Java Faker 伪…

【c++】list的特性及使用

目录 一、list的介绍 二、list的深度剖析与模拟实现 1、list图解 2、list增删查改模拟实现 三、list与vector的对比 一、list的介绍 STL中的list指的是带头双向循环链表。list是可以在常数范围内任意位置进行插入和删除的序列式容器&#xff0c;并且可以前后双向迭代。lis…

Activiti7官方在线流程设计器下载和部署

文章目录 一、流程设计器下载二、流程设计器简单运行三、流程设计器简单使用四、流程设计器持久化持久化会遇到的常见错误 五、流程设计器汉化说明菜单汉化操作汉化 参考文档 一、流程设计器下载 官网下载地址&#xff1a;https://www.activiti.org/get-started 点击直接获取官…

Flutter 小技巧之升级适配 Xcode15

美好的 2024 从「适配」开始&#xff0c;按照苹果的尿性&#xff0c;2024 春季开始大家将不得使用 Xcode15 来构建 App &#xff0c;另外根据《2024 的 iOS 的隐私清单》 要求&#xff0c;使用 Flutter 的开发者是无法逃避适配 Xcode15 更新的命运。 另外&#xff0c;众所周知…

vue3组件传参

1、props: 2、自定义事件子传父 3、mitt任意组件通讯 4、v-model通讯(v-model绑定在组件上) (1)V2中父子组件的v-model通信&#xff0c;限制了popos接收的属性名必须为value和emit触发的事件名必须为input,所以有时会有冲突; 父组件: 子组件: (2)V3中:限制了popos接收的属性名…

详解Java死锁-检测与解决

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;咱们今天来聊聊死锁。特别是对于咱们这些Java程序员来说&#xff0c;死锁就像是隐藏在暗处的陷阱&#xff0c;稍不注意就会掉进去。但别担心&#xff0c;小黑今天就来带大家一探究竟&#xff0c;看看怎么样才能避…

什么是短视频矩阵系统?效果是怎么样的?

短视频矩阵系统是一种通过将多个短视频连接起来形成一个整体的系统。它的效果是可以提供一种连贯而有序的观看体验&#xff0c;使观众可以连续地观看一系列相关的短视频内容。 短视频矩阵系统的运作方式如下&#xff1a;首先&#xff0c;用户在平台上选择一个短视频开始观看。…

一款开源的MES系统

随着工业4.0的快速发展&#xff0c;制造执行系统&#xff08;MES&#xff09;成为了智能制造的核心。今天&#xff0c;将为大家推荐一款开源的MES系统——iMES工厂管家。 什么是iMES工厂管家 iMES工厂管家是一款专为中小型制造企业打造的开源MES系统。它具备高度的可定制性和灵…

刷了四百道算法题,我在项目里用过哪几道呢?

大家好&#xff0c;我是老三&#xff0c;今天和大家聊一个话题&#xff1a;项目中用到的力扣算法。 不知道从什么时候起&#xff0c;算法已经成为了互联网面试的标配&#xff0c;在十年前&#xff0c;哪怕如日中天的百度&#xff0c;面试也最多考个冒泡排序。后来&#xff0c;…

强化学习的数学原理学习笔记 - 策略梯度(Policy Gradient)

文章目录 概览&#xff1a;RL方法分类策略梯度&#xff08;Policy Gradient&#xff09;Basic Policy Gradient目标函数1&#xff1a;平均状态值目标函数2&#xff1a;平均单步奖励&#x1f7e1;PG梯度计算 &#x1f7e6;REINFORCE 本系列文章介绍强化学习基础知识与经典算法原…

android的求职APP 前端+后端

一 项目名称 基于android的求职APP&#xff0c;包含前台和后台管理系统的&#xff0c;前端主要移动端&#xff0c;应聘者注册账号&#xff0c;然后登陆&#xff0c;完善自己的简历&#xff0c;然后根据自己的需要投递岗位&#xff0c;查看面试邀请&#xff0c;后台主要维护数据…

听GPT 讲Rust源代码--compiler(34)

File: rust/compiler/rustc_middle/src/ty/print/mod.rs 在Rust源代码中&#xff0c;文件rust/compiler/rustc_middle/src/ty/print/mod.rs的作用是定义了打印类型和其他相关信息的功能。 具体来说&#xff0c;该文件中定义了三个trait&#xff0c;分别为Print<tcx>、Pri…

Java_特殊文件

一、属性文件 1.1 特殊文件概述 前面学习了IO流&#xff0c;知道IO流是用来读、写文件中的数据。但是接触到的文件都是普通的文本文件&#xff0c;普通的文本文件里面的数据是没有任何格式规范的&#xff0c;用户可以随意编写&#xff0c;如下图所示。 像这种普通的文本文件…