2024.04.25_学习日记
天气:晴
学习地点:图书馆
学习时长:10h
学习内容
- 二叉树高度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36class Node: # 定义树节点的类
def __init__(self, val=None):
self.val = val # 节点的值
self.left = None # 指向左子节点的指针
self.right = None # 指向右子节点的指针
def buildtree(preorder, inorder): # 构建树的函数
if not preorder or not inorder: # 如果先序或中序列表为空,返回None
return None
root_val = preorder[0] # 根节点的值是先序列表的第一个元素
index = inorder.index(root_val) # 找到根节点在中序列表中的索引
inorder_left = inorder[:index] # 左子树的中序列表
inorder_right = inorder[index+1:] # 右子树的中序列表
preorder_left = preorder[1:index+1] # 左子树的先序列表
preorder_right = preorder[index+1:] # 右子树的先序列表
root = Node(root_val) # 创建一个以根节点值为值的节点
root.left = buildtree(preorder_left, inorder_left) # 递归构建左子树
root.right = buildtree(preorder_right, inorder_right) # 递归构建右子树
return root # 返回子树的根节点
def getheight(root): # 计算树的高度的函数
if not root: # 如果根节点为空,返回0
return 0
left = getheight(root.left) # 计算左子树的高度
right = getheight(root.right) # 计算右子树的高度
return max(left, right) + 1 # 返回左右子树高度的最大值加1
while True:
try:
n = int(input()) # 输入n,表示节点数
preorder = input() # 输入先序遍历结果
inorder = input() # 输入中序遍历结果
root = buildtree(preorder, inorder) # 构建树
print(getheight(root)) # 打印树的高度
except: # 捕获异常
break # 退出循环 - 图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29def dfs(visited, x, y, graph, curres):
if x == y: # 如果当前节点为目标节点 y,则返回当前累积距离
return curres
visited[x] = True # 将当前节点标记为已访问
minres = float('inf') # 初始化最小距离为无穷大
for nxt, distance in graph[x]: # 遍历当前节点的邻居节点及其距离
if not visited[nxt]: # 如果邻居节点未被访问过
# 递归调用 DFS,并更新最小距离
minres = min(minres, dfs(visited, nxt, y, graph, curres + distance))
visited[x] = False # 恢复当前节点的访问状态
return minres # 返回最小距离
while True:
try:
n, m = map(int, input().split()) # 输入节点数和边数
graph = {i: [] for i in range(1, n + 1)} # 创建图的邻接表
for i in range(m): # 读取每条边的起点、终点和距离
a, b, l = map(int, input().split())
graph[a].append((b, l)) # 将边加入图的邻接表中
graph[b].append((a, l)) # 无向图需双向添加
x, y = map(int, input().split()) # 输入起点和终点
visited = [False] * (1 + n) # 初始化节点访问状态
res = dfs(visited, x, y, graph, 0) # 调用 DFS 查找最短路径长度
if res == float('inf'): # 如果最短路径长度为无穷大
print('No path') # 输出无法到达的提示
else:
print(res) # 输出最短路径长度
except:
break # 捕获异常并退出循环 - 不知道第几次的KMP(lc28)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40class Solution:
def strStr(self, haystack: str, needle: str) -> int:
# 定义一个函数用于生成 needle 的 next 数组
def getnext():
nlen = len(needle)
if nlen == 1:
return [-1] # 特殊情况:needle 长度为 1
nextlist = [0] * nlen # 初始化 next 数组
nextlist[0] = -1 # 初始值设为 -1
nextlist[1] = 0 # next 数组的第二个元素设为 0
cn = 0 # cn 表示当前 next 数组的索引
i = 2 # 从第三个元素开始计算 next 数组
while i < nlen:
if needle[i-1] == needle[cn]:
nextlist[i] = cn + 1 # 如果当前字符与前缀相等,更新 next 数组的值
i += 1
cn += 1
elif cn > 0:
cn = nextlist[cn] # 回溯到前一个可能的相等前缀
else:
nextlist[i] = 0 # 如果没有相等前缀,将当前 next 数组值设为 0
i += 1
return nextlist
list1 = getnext() # 调用函数生成 needle 的 next 数组
i = 0
j = 0
mlen = len(haystack) # haystack 的长度
nlen = len(needle) # needle 的长度
if mlen < nlen:
return -1 # 如果 haystack 的长度小于 needle 的长度,直接返回 -1
while i < mlen and j < nlen:
if haystack[i] == needle[j]:
i += 1
j += 1
elif list1[j] == -1: # 如果匹配失败且 next 数组的值为 -1,表示 needle 的第一个字符就不匹配
i += 1
else:
j = list1[j] # 回溯到可能的相等前缀的下一个位置
return i - j if j == nlen else -1 # 返回最终匹配的位置,或者 -1 表示未找到 - 重复子串(KMP lc459)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26class Solution:
def repeatedSubstringPattern(self, s: str) -> bool:
n = len(s) # 获取字符串 s 的长度
s1 = s + ' ' # 将字符串 s 后面添加一个空格,方便后续处理
if n == 1: # 如果字符串长度为 1,直接返回 False
return False
kmplist = [0] * (n + 1) # 初始化一个长度为 n+1 的列表,用于存储 KMP 算法中的 next 数组
kmplist[0] = -1 # 初始化第一个元素为 -1
kmplist[1] = 0 # 初始化第二个元素为 0
i = 2 # 从第三个元素开始计算 next 数组
cn = 0 # 初始化当前 next 数组索引为 0
while i < n + 1: # 循环计算 next 数组的值
if s[i - 1] == s[cn]: # 如果当前字符与前缀相等
kmplist[i] = cn + 1 # 更新 next 数组的值
i += 1
cn += 1
elif cn > 0: # 如果当前字符不等于前缀的最后一个字符,但是 cn 大于 0
cn = kmplist[cn] # 回溯到前一个可能的相等前缀
else: # 如果以上两个条件都不满足
kmplist[i] = 0 # 将当前 next 数组值设为 0
i += 1
# 判断重复子字符串的条件:最后一个元素的值不为 0,并且字符串长度能整除 (长度 - 最后一个元素的值)
if kmplist[-1] != 0 and (n % (n - kmplist[-1]) == 0):
return True # 满足条件则返回 True,表示存在重复子字符串
else:
return False # 否则返回 False,表示不存在重复子字符串