前言
- 干活炼丹闲暇之余来刷刷题!NoNo应该说刷题闲暇才炼丹
994. 腐烂的橘子 - 力扣(LeetCode)
-
BFS队列
- 参考橘子哥的题解
-
class Solution: def orangesRotting(self, grid: List[List[int]]) -> int: row, col, time = len(grid), len(grid[0]), 0 q = 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] = 2 q.append((i0, j0, time+1)) if any(1 in row for row in grid): return -1 # 如果最后还有新鲜橘子就返回-1 return 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 = 0 while 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 += 1 return 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的课程入列 # dfs while q: cur = q.popleft() numCourses -= 1 # 选掉一门课 relations = relations_list[cur] for i in relations: indegrees[i] -= 1 # 如果存在后续课程则后续课程入度-1 if 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 True adjacency = [[] 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.root for 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.root for c in word: c_index = ord(c) - ord('a') if cur.next[c_index]: cur = cur.next[c_index] else: return False return cur.is_end # 匹配前缀 def startsWith(self, prefix: str) -> bool: cur = self.root for c in prefix: c_index = ord(c) - ord('a') if cur.next[c_index]: cur = cur.next[c_index] else: return False return 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)
后言
- 这几个今天都没怎么接触,学完感觉头好痒,啊啊啊要长脑子了