算法编程题-删除子文件夹

算法编程题-删除子文件夹

      • 原题描述
      • 设计思路
      • 代码实现
      • 复杂度分析

前一段时间面试字节的时候,被问到gin框架的路由结构。gin框架的路由结构采用的一般是前缀树来实现,于是被要求手写前缀树来实现路由的注册和查找。
本文以 leetcode 1233为例介绍一下前缀树(字典树)。

原题描述

原题为有很多类似于unit风格的文件夹,如\tmp, \usr\local, 且保证这些文件夹是合法的,不会存在类似于usr或者\usr\local\之类的,现在要求删除所有的子文件夹,返回剩余的文件夹。

设计思路

该题可以采用前缀树加深度优先搜索来实现。
前缀树又名字典树,本质上讲就是一个多叉树,每一个节点保存一个字符或者一个字符串,基于公共前缀可以以较少的内存空间保存这些数据,并且实现较高的查询速率。
在本题中,可以用树中的每一个节点来保存一个文件夹的一个级别,然后节点额外维护一个变量,标识是否有文件夹结束在这一个节点上。然后用深度优先搜索搜索这根树,如果搜索到一个节点,发现有一个文件夹结束在这一个节点上,说明这个分支不用搜索了,因为这个分支下如果还有文件夹也一定是结束在这一个节点上的文件夹的子文件夹。

代码实现

首先是前缀树的实现,代码如下:

type PrefixTreeNode[T comparable] struct {key T    // 当前树节点名称children map[T]*PrefixTreeNode[T]  // 子节点isEnd  bool  // 表示是否有一个元素结束在该节点上value interface{}
}func NewPrefixTreeNode[T comparable](key T, value interface{}, isEnd bool) *PrefixTreeNode[T] {return &PrefixTreeNode[T]{key: key, value: value, isEnd: isEnd, children: make(map[T]*PrefixTreeNode[T])}
}type PrefixTree[T comparable] struct {root *PrefixTreeNode[T]
}func NewPrefixTree[T comparable]() *PrefixTree[T] {return &PrefixTree[T]{root: &PrefixTreeNode[T]{children: make(map[T]*PrefixTreeNode[T])}}
}// Insert 根据keyPath插入一系列节点,最后一个节点的值赋值或者更新为value
func (t *PrefixTree[T]) Insert(keyPath []T, value interface{}) {tr := t.rootn := len(keyPath)i := 0for i < n {if nextNode, ok := tr.children[keyPath[i]]; ok {tr = nextNodei++} else {for i < n {newNode := NewPrefixTreeNode(keyPath[i], nil, false)tr.children[keyPath[i]] = newNodetr = newNodei++}}}tr.isEnd = truetr.value = value
}// Search 搜索前缀树,返回最后一个节点绑定的值,如果没找到,则第二个返回值为false
func (t *PrefixTree[T]) Search(keyPath []T) (interface{}, bool) {tr := t.rootn := len(keyPath)i := 0for i < n {if nextNode, ok := tr.children[keyPath[i]]; ok {tr = nextNodei++} else {return nil, false}}return tr.value, true
}// GetShortestKey 返回前缀树所有特殊前缀,树中不存在其他前缀以这些前缀为前缀
func (t *PrefixTree[T]) GetShortestKey() [][]T {res := make([][]T, 0)var dfs func(curNode *PrefixTreeNode[T], cur []T) dfs = func(curNode *PrefixTreeNode[T], cur []T) {if curNode.isEnd {res = append(res, append([]T(nil), cur...))return}for _, child := range curNode.children {dfs(child, append(cur, child.key))}}dfs(t.root, make([]T, 0))return res
}

在实现上,使用了泛型和闭包,闭包就是在函数中定义函数,这样做的好处可以增加可读性,减少冗余代码和变量,适用于该函数独特使用的工具函数。然后再来看深度优先搜索的代码实现,如下:

func removeSubfolders(folder []string) []string {t := NewPrefixTree[string]()for _, f := range folder {paths := strings.Split(f, "/")newPaths := make([]string, 0)for i := 0; i < len(paths); i++ {if len(paths[i]) > 0 {newPaths = append(newPaths, "/" + paths[i])}}t.Insert(newPaths, nil)}res := t.GetShortestKey()ans := make([]string, len(res))for i, each := range res {ans[i] = strings.Join(each, "")}return ans
}

leetcode运行截图如下:
在这里插入图片描述

复杂度分析

  • 时间复杂度: O ( n m ) O(nm) O(nm), 其中n为文件夹的数量,m为最长层级文件夹的层级数
  • 空间复杂度: O ( m n ) O(mn) O(mn)

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

利用SSH中的弱私钥

import paramiko import argparse import os from threading import Thread, BoundedSemaphore # 设置最大连接数 maxConnections 5 # 创建一个有界信号量&#xff0c;用于控制同时进行的连接数 connection_lock BoundedSemaphore(valuemaxConnections) # 用于控制是否停止所…

力扣整理版七:二叉树(待更新)

满二叉树&#xff1a;如果一棵二叉树只有度为0的结点和度为2的结点&#xff0c;并且度为0的结点在同一层上&#xff0c;则这棵二叉树为满二叉树。深度为k&#xff0c;有2^k-1个节点的二叉树。 完全二叉树&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&am…

如何使用可靠UDP协议(KCP)

希望这篇文章&#xff0c;对学习和使用 KCP 协议的读者&#xff0c;有帮助。 1. KCPUDP 流程图 2. 示例代码 #include <iostream>int main() {// 代码太多&#xff0c;暂存仓库return 0; } 具体使用&#xff0c;请参考代码仓库&#xff1a;https://github.com/ChivenZha…

论文复述:(TRPCA)t-Shatten-p

一个基于TNN-TRPCA的简单创新的论文&#xff0c;Tensor Robust PCA主要是将一个tensor分解为low-rank和sparse两个component&#xff0c;主要思想是引入了weighted tensor Schatten-p norm进行建模。

6_协议与层次划分

在计算机网络中要做到有条不紊地交换数据&#xff0c;就必须遵守一些事先约定好的规则。这些规则明确规定了所交换的数据的格式以及有关的同步问题。这里所说的是狭义的(即同频或同频同相) 而是广义的&#xff0c;即在一定的条件下应当发生什么事件 (例如&#xff0c;应当发送一…

微服务--Gateway网关--全局Token过滤器【重要】

全局过滤器 GlobalFilter&#xff0c; 注入到 IOC里面即可 概念&#xff1a; 全局过滤器&#xff1a; 所有的请求 都会在执行链里面执行这个过滤器 如添加日志、鉴权等 创建一个全局过滤器的基本步骤&#xff1a; 步骤1: 创建过滤器类 首先&#xff0c;创建一个实现了Globa…

Kafka进阶_1.生产消息

文章目录 一、Controller选举二、生产消息2.1、创建待发送数据2.2、创建生产者对象&#xff0c;发送数据2.3、发送回调2.3.1、异步发送2.3.2、同步发送 2.4、拦截器2.5、序列化器2.6、分区器2.7、消息可靠性2.7.1、acks 02.7.2、acks 1(默认)2.7.3、acks -1或all 2.8、部分重…

STL C++ CookBook 7:迭代器简论

目录 兼容的迭代器 迭代器概念 使用迭代器来填充STL的容器 将一些序列算法包装成可迭代的 构建 zip 迭代器适配器 兼容的迭代器 迭代器是 STL 中的一个基本概念。迭代器使用 C 指针的语义实现&#xff0c;使用相同的递增、递减和解引用运算符。 大多数 C/C 程序员都熟悉指…

【Python图解】 常量与变量及基本运算

【图解python】 常量与变量及基本运算 Python 常量与变量教程 可能你现在会产生疑惑&#xff0c;代码中的 print 代表什么意义&#xff1f;括号又是什么作用&#xff1f;为什么 hello world 外面有个双引号&#xff1f;没关系&#xff0c;下面我们就来了解 Python 语法的奥秘…

「漏洞复现」全新优客API接口管理系统 index/doc SQL注入漏洞

0x01 免责声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;作者不为此承担任何责任。工具来自网络&#xff0c;安全性自测&#xff0c;如有侵权请联系删…

java ssm 健康医馆管理系统 中医馆管理 健康平台 药店 源码jsp

一、项目简介 本项目是一套基于SSM的健康医馆管理系统&#xff0c;主要针对计算机相关专业的和需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本、软件工具等。 项目都经过严格调试&#xff0c;确保可以运行&#xff01; 二、技术实现 ​后端技术&#x…

Python - jieba库的使用

文章目录 jieba库概述jieba分词的三种模式jieba库的安装 jieba分词的原理jieba库常用函数实例 : 文本词频统计 jieba库概述 jieba是优秀的中文分词第三方库 中文文本需要通过分词获得单个的词语jieba是优秀的中文分词第三方库&#xff0c;需要额外安装jieba库提供三种分词模式…

一个简单的图像分类项目(九)并行训练的学习:多GPU的DP(DataParallel数据并行)

将电脑装成Ubuntu、Windows双系统&#xff0c;并在Ubuntu上继续学习。 在现代深度学习中&#xff0c;多主机多GPU训练已经变得非常常见&#xff0c;尤其是对于大规模模型和数据集。最简单和早期的并行计算比如NVIDIA的SLI&#xff0c;从NVIDIA 450系列驱动开始&#xf…

本草智选:中药实验管理的智能推荐

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了中药实验管理系统的开发全过程。通过分析中药实验管理系统管理的不足&#xff0c;创建了一个计算机管理中药实验管理系统的方案。文章介绍了中药实验管理系统的系…

凸优化理论和多模态基础模型研究

文章目录 摘要Abstract1. 拉格朗日对偶问题1.1 弱对偶问题1.2 强对偶问题&#xff08;P*D*&#xff09;1.3 KKT条件 2. 论文阅读3. 总结 摘要 本周从拉格朗日对偶理论出发&#xff0c;系统学习了优化问题中凸函数、强对偶条件以及 KKT 条件的应用&#xff0c;并将其与机器学习…

nginx+vconsole调试网页在vivo浏览器无法显示图片问题

一、问题描述 昨天测试小伙伴提了一个特殊的bug&#xff0c;在安卓vivo手机浏览器上访问网页&#xff0c;网页的图片按钮和录播图一闪而过后便消失不见&#xff1a; 二、问题排查 项目采用Nuxt框架&#xff0c;排查的方向大致如下&#xff1a; 1.其它手机浏览器是否有复现&am…

草本追踪:中药实验管理的数字化转型

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

【Linux】虚拟地址空间,页表,物理内存

目录 进程地址空间&#xff0c;页表&#xff0c;物理内存 什么叫作地址空间&#xff1f; 如何理解地址空间的区域划分&#xff1f; 地址空间结构体 为什么要有地址空间&#xff1f; 页表 cr3寄存器 权限标记位 位置标记位 其他 每个存储单元是一个字节&#xff0c;一…

集群聊天服务器(3)muduo网络库

目录 基于muduo的客户端服务器编程 muduo只能装在linux中&#xff0c;依赖boost库 客户端并不需要高并发 基于muduo的客户端服务器编程 支持epoll线程池&#xff0c;muduo封装了线程池 而且还有完善的日志系统 使用muduo库代码非常固定&#xff0c;基本就只有chatserver的类名…

【Python刷题】最少拐弯路线问题

题目描述 洛谷P1649 一、题目理解 首先&#xff0c;我们来看一下这道题目的要求。题目给定了一个 NN&#xff08;1≤N≤100&#xff09; 的方格&#xff0c;方格中的每个格子有不同的状态&#xff0c;用 . 表示可以行走的格子&#xff0c;x 表示不能行走的格子&#xff0c;…