前言
- 干活炼丹闲暇之余来刷刷题!NoNo应该说刷题闲暇才炼丹
994. 腐烂的橘子 - 力扣(LeetCode)
-
BFS队列
- 参考橘子哥的题解
-
class Solution:def orangesRotting(self, grid: List[List[int]]) -> int:row, col, time = len(grid), len(grid[0]), 0q = deque() # 把所有腐烂橘子存入队列,多点开花for i in range(row):for j in range(col):if grid[i][j] == 2:q.append((i, j, 0)) # 0标记当前时间/深度# 多源BFS过程while q:i, j, time = q.popleft()for i0, j0 in ((i-1,j), (i, j-1), (i+1, j), (i, j+1)):if 0 <= i0 < row and 0 <= j0 < col and grid[i0][j0] == 1:grid[i0][j0] = 2q.append((i0, j0, time+1))if any(1 in row for row in grid):return -1 # 如果最后还有新鲜橘子就返回-1return time
-
BFS双集合
-
class Solution:def orangesRotting(self, grid: List[List[int]]) -> int:row = len(grid)col = len(grid[0])rotten = {(i, j) for i in range(row) for j in range(col) if grid[i][j] == 2} # 腐烂集合fresh = {(i, j) for i in range(row) for j in range(col) if grid[i][j] == 1} # 新鲜集合time = 0while fresh:if not rotten: return -1 # 没有腐烂有新鲜# 遍历腐烂的,感染周围新鲜一波,原来腐烂的从集合中删除,新腐烂加进集合rotten = {(i + di, j + dj) for i, j in rotten for di, dj in [(0, 1), (0, -1), (1, 0), (-1, 0)] if (i + di, j + dj) in fresh}fresh -= rotten # 剔除腐烂的time += 1return time
-
207. 课程表 - 力扣(LeetCode)
-
BFS拓扑排序
-
判断是否是有向无环图(DAG)用到拓扑排序,学习一下B站视频和题解
-
class Solution:def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:indegrees = [0] * numCourses # 入度数组(列表,保存所有课程的依赖课程总数)relations_list = collections.defaultdict(list) # 邻接表(字典,保存所有课程与依赖课程的关系,int:list)# relations_list = [[] for _ in range(numCourses)] # 也可以用二维数组for cur, pre in prerequisites:indegrees[cur] += 1 # 保存课程初始入度值relations_list[pre].append(cur) # 添加依赖它的后续课程q = deque()for i in range(len(indegrees)):if indegrees[i] == 0:q.append(i) # 将入度为0的课程入列# dfswhile q:cur = q.popleft()numCourses -= 1 # 选掉一门课relations = relations_list[cur]for i in relations: indegrees[i] -= 1 # 如果存在后续课程则后续课程入度-1if indegrees[i] == 0:q.append(i) # 将入度为0的课程入列# 如果上完了说明没有环return numCourses == 0
-
-
DFS判断环
- 参考K神题解
-
class Solution:def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:def dfs(i, adjacency, flags):if flags[i] == -1: return True # 别人走过的,没问题if flags[i] == 1: return False # 走过走过的,坏了,告诉上一层flags[i] = 1 # 1表示我自己走的for j in adjacency[i]:if not dfs(j, adjacency, flags): return False # 接收下层的信号,此路有环!flags[i] = -1 # -1表示别人走的return Trueadjacency = [[] for _ in range(numCourses)]flags = [0 for _ in range(numCourses)] # 0表示没走过for cur, pre in prerequisites:adjacency[pre].append(cur)for i in range(numCourses):if not dfs(i, adjacency, flags): return False # 如果有路坏的就有环return True
208. 实现 Trie (前缀树) - 力扣(LeetCode)
-
前缀树
- 这也是图?没都没听过,学习一下小白题解
-
# 节点类 class Node:def __init__(self):self.is_end = False # 标记是否到达单词结尾self.next = [None]*26 # 每个位置对应一个字母,连下一个节点 # 前缀树类 class Trie:# 初始化根节点def __init__(self):self.root = Node()# 插入单词:匹配前缀 + 补充剩余def insert(self, word: str) -> None:cur = self.rootfor c in word:c_index = ord(c) - ord('a')if not cur.next[c_index]:cur.next[c_index] = Node() # 前缀匹配到存在该字母cur = cur.next[c_index]cur.is_end = True# 搜索单词:匹配前缀,检查是否为结尾def search(self, word: str) -> bool:cur = self.rootfor c in word:c_index = ord(c) - ord('a')if cur.next[c_index]:cur = cur.next[c_index]else:return Falsereturn cur.is_end# 匹配前缀def startsWith(self, prefix: str) -> bool:cur = self.rootfor c in prefix:c_index = ord(c) - ord('a')if cur.next[c_index]:cur = cur.next[c_index]else:return Falsereturn True# Your Trie object will be instantiated and called as such: # obj = Trie() # obj.insert(word) # param_2 = obj.search(word) # param_3 = obj.startsWith(prefix)
后言
- 这几个今天都没怎么接触,学完感觉头好痒,啊啊啊要长脑子了