力扣207.课程表、208.实现Trie(前缀树)

207.课程表

思路:

主要是要求构成有向无环图,详细的思路如参考链接的方法二所示,我把我理解了的代码都标注在了注释里,因为确实有点看不太懂,还要再消化一下。

复杂度分析:

  • 时间复杂度 O(N+M): 遍历一个图需要访问所有节点和所有临边,N 和 M 分别为节点数量和临边数量;
  • 空间复杂度 O(N+M): 为建立邻接表所需额外空间,adjacency 长度为 N ,并存储 M 条临边的数据。

参考:

https://leetcode.cn/problems/course-schedule/solutions/18806/course-schedule-tuo-bu-pai-xu-bfsdfsliang-chong-fa

代码:

python 复制代码
class Solution:
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        # 参数:第i门课程;每门课程的所有前置课程构成邻接矩阵;标志位,用于记录该门课程是(1)否(0)被当前节点访问过以及是否被其他节点访问过(-1)
        def dfs(i, adjacency, flags):
            
            if flags[i] == -1: return True  # 说明当前访问节点已被其他节点启动的 DFS 访问,无需再重复搜索,直接返回 True
            if flags[i] == 1: return False  # 说明在本轮 DFS 搜索中节点 i 被第 2 次访问,即 课程安排图有环 ,直接返回 False
            
            flags[i] = 1  # 该轮此节点标为已访问
            
            # 对该节点的每一个邻接节点(前置课程)都验证是否满足无环的条件
            for j in adjacency[i]:
                if not dfs(j, adjacency, flags): return False
            
            # 都验证完确实无环之后,将标志设置为本轮该节点已访问,不影响之后判断
            flags[i] = -1
            return True

        # 初始化邻接矩阵和标志
        adjacency = [[] for _ in range(numCourses)]
        flags = [0 for _ in range(numCourses)]

        # cur为当前课程,pre为其前置课程,对应加入
        for cur, pre in prerequisites:
            adjacency[cur].append(pre)

        for i in range(numCourses):
            if not dfs(i, adjacency, flags): return False

        return True

208.实现Trie(前缀树)

思路:

1、由于一系列处理都是基于字符串的,所以可以把数据结构想象为一个26叉树,每一分支表示一个字母,各个节点有自己的子节点和是否字符串结束两个标志用以记录

2、搜索字符串和字符串前缀可用一个find函数来返回不同数值进行判断,其余的操作和二叉树类似,每处理完要向子节点移动等等,更具体的可以看代码注释

复杂度分析:

  • 时间复杂度:初始化为 O(1),insert 为 O(n∣Σ∣),其余为 O(n),其中 n 是 word 的长度,∣Σ∣=26 是字符集合的大小。注意创建一个节点需要 O(∣Σ∣) 的时间(如果用的是数组)。
  • 空间复杂度:O(qn∣Σ∣)。其中 q 是 insert 的调用次数。

参考:

https://leetcode.cn/problems/implement-trie-prefix-tree/solutions/2993894/cong-er-cha-shu-dao-er-shi-liu-cha-shu-p-xsj4

代码:

python 复制代码
class Node:
    __slots__ = 'son', 'end'  # 声明该类的实例将拥有的属性

    def __init__(self):
        self.son = {}  # 字典,存储该节点的子节点
        self.end = False  # 表示该节点是否是一个单词的结尾

# 当成一个26叉树来处理
class Trie:

    def __init__(self):
        self.root = Node()

    def insert(self, word: str) -> None:
        cur = self.root
        for c in word:
            # 若字符不在子节点中,就创建一个新节点
            if c not in cur.son:
                cur.son[c] = Node()
            cur = cur.son[c]  # 相当于往下一层遍历移动一个节点

        cur.end = True

    def find(self, word):
        cur = self.root
        for c in word:
            # 若字符不在子结点中,直接返回0值
            if c not in cur.son:
                return 0
            cur = cur.son[c]
        # 在原有的树中找到了和word相同的路径(2=完全匹配,1=前缀匹配)
        return 2 if cur.end else 1

    def search(self, word: str) -> bool:
        return self.find(word) == 2

    def startsWith(self, prefix: str) -> bool:
        return self.find(prefix) != 0
相关推荐
喝茶与编码13 小时前
Python异步并发控制:asyncio.gather 与 Semaphore 协同设计解析
后端·python
zone773913 小时前
003:RAG 入门-LangChain 读取图片数据
后端·python·面试
用户83562907805113 小时前
在 PowerPoint 中用 Python 添加和定制形状的完整教程
后端·python
用户9623779544814 小时前
🚀 docx2md-picgo:Word 文档图片一键上传图床工具
python·markdown
zone77392 天前
001:简单 RAG 入门
后端·python·面试
F_Quant2 天前
🚀 Python打包踩坑指南:彻底解决 Nuitka --onefile 配置文件丢失与重启报错问题
python·操作系统
允许部分打工人先富起来2 天前
在node项目中执行python脚本
前端·python·node.js
IVEN_2 天前
Python OpenCV: RGB三色识别的最佳工程实践
python·opencv
haosend2 天前
AI时代,传统网络运维人员的转型指南
python·数据网络·网络自动化
曲幽2 天前
不止于JWT:用FastAPI的Depends实现细粒度权限控制
python·fastapi·web·jwt·rbac·permission·depends·abac