207.课程表
思路:
主要是要求构成有向无环图,详细的思路如参考链接的方法二所示,我把我理解了的代码都标注在了注释里,因为确实有点看不太懂,还要再消化一下。
复杂度分析:
- 时间复杂度 O(N+M): 遍历一个图需要访问所有节点和所有临边,N 和 M 分别为节点数量和临边数量;
- 空间复杂度 O(N+M): 为建立邻接表所需额外空间,adjacency 长度为 N ,并存储 M 条临边的数据。
参考:
代码:
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 的调用次数。
参考:
代码:
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