AI刷题记录(三) | 豆包MarsCode AI刷题
课程表
问题描述
你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。
在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。
- 例如,先修课程对
[0, 1]表示:想要学习课程0,你需要先完成课程1。
请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。
思路
建bi -> ai的边,然后从每个没有入度的根节点搜索,使用vis记录当次搜索的状态,使用flag记录总的访问情况。当vis[u]==True,说明节点已经被访问过,说明遇到环了,答案返回false;flag[u]==True,则跳过。
代码
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
e = [[] for _ in range(numCourses)]
in_deg = [0] * numCourses
vis = [0] * numCourses
flag = [0] * numCourses
for v, u in prerequisites:
e[u].append(v)
in_deg[v] += 1
def dfs(u) -> bool:
vis[u] += 1
flag[u] += 1
ret = True
for v in e[u]:
if vis[v] > 0:
ret = False
break
if flag[v] > 0: continue
res = dfs(v)
if res == False:
ret = False
break
vis[u] -= 1
return ret
for i in range(numCourses):
if in_deg[i] > 0: continue
res = dfs(i)
if res == False: return False
if sum(flag) != numCourses: return False
return True
网络延迟时间
问题描述
有 n 个网络节点,标记为 1 到 n。
给你一个列表 times,表示信号经过 有向 边的传递时间。 times[i] = (ui, vi, wi),其中 ui 是源节点,vi 是目标节点, wi 是一个信号从源节点传递到目标节点的时间。
现在,从某个节点 K 发出一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1 。
思路
使用搜索或者最短路均可,需要考虑会重复经过一个节点的问题,使用dis数组表示从根到该节点的最短距离,若当前花费小于dis内的值,则直接退出即可,否则更新并继续深入搜索。
代码
class Solution:
def networkDelayTime(self, times: List[List[int]], n: int, k: int) -> int:
adj = [[] for _ in range(n)]
dis = [int(1e9)] * n
for t in times:
u, v, w = t
adj[u-1].append((v-1, w))
def dfs(u, t):
if dis[u] <= t: return
dis[u] = t
for v, w in adj[u]:
dfs(v, t + w)
dfs(k-1, 0)
if sum((1 for x in dis if x < int(1e9) )) < n: return -1
return max((x for x in dis if x < int(1e9) ))
最大矩形面积
问题描述
小S最近在分析一个数组 ,数组的每个元素代表某种高度。小S对这些高度感兴趣的是,当我们选取任意 个相邻元素时,如何计算它们所能形成的最大矩形面积。
对于 个相邻的元素,我们定义其矩形的最大面积为:
即, 的值为这 个相邻元素中的最小值乘以 。现在,小S希望你能帮他找出对于任意 , 的最大值。
思路
-
暴力解法:
- 对于每个可能的
k(从 1 到n),遍历数组,计算每个k个相邻元素的矩形面积,并记录最大值。 - 时间复杂度为
O(n^2),对于较大的n可能不够高效。
- 对于每个可能的
-
优化思路:
- 使用单调栈来优化查找最小值的过程。
- 单调栈可以帮助我们在
O(n)时间内找到每个元素作为最小值时,能形成的最大矩形面积。
数据结构选择
-
单调栈:
- 单调栈可以用来维护一个递增或递减的序列。
- 我们可以利用单调栈来快速找到每个元素作为最小值时,能形成的最大矩形面积。
算法步骤
-
初始化:
- 创建一个单调栈,用于存储数组元素的索引。
- 创建一个数组
left和right,分别记录每个元素作为最小值时,能向左和向右扩展的最大范围。
-
遍历数组:
- 从左到右遍历数组,维护单调栈。
- 对于每个元素,计算其作为最小值时,能向左扩展的最大范围。
- 从右到左遍历数组,计算其作为最小值时,能向右扩展的最大范围。
-
计算最大面积:
- 对于每个元素,计算其作为最小值时,能形成的最大矩形面积。
- 记录并返回最大面积。
代码
def solution(n, array):
# 初始化单调栈和左右扩展范围数组
stack = []
left = [0] * n
right = [0] * n
# 从左到右遍历数组,计算每个元素作为最小值时,能向左扩展的最大范围
for i in range(n):
while stack and array[stack[-1]] >= array[i]:
stack.pop()
left[i] = stack[-1] if stack else -1
stack.append(i)
stack = []
# 从右到左遍历数组,计算每个元素作为最小值时,能向右扩展的最大范围
for i in range(n-1, -1, -1):
while stack and array[stack[-1]] >= array[i]:
stack.pop()
right[i] = stack[-1] if stack else n
stack.append(i)
return max(array[i] * (right[i] - left[i] - 1) for i in range(n))
if __name__ == "__main__":
# Add your test cases here
print(solution(5, [1, 2, 3, 4, 5]) == 9)