题目:
给你一个正整数 n
,它表示一个 有向无环图 中节点的数目,节点编号为 0
到 n - 1
(包括两者)。
给你一个二维整数数组 edges
,其中 edges[i] = [fromi, toi]
表示图中一条从 fromi
到 toi
的单向边。
请你返回一个数组 answer
,其中 answer[i]
是第 i
个节点的所有 祖先 ,这些祖先节点 升序 排序。
如果 u
通过一系列边,能够到达 v
,那么我们称节点 u
是节点 v
的 祖先 节点。
思考:
1. 先用邻接矩阵构造图,记录每个节点的相邻祖先。
2. 然后计算每个节点i的所有祖先ans[i]。用一个队列queue记录节点i的待判断祖先,初始化为节点的相邻祖先。
3. 每次取出队列中一个节点x,将x加入ans[i]。若x小于i(x的ans已经计算完成),则将ans[x]中的元素全部加入ans[i];否则,将x的相邻祖先加入队列queue。直到queue取空为止。
4. 每次计算完ans[i]后,去除重复的节点,并排序。
代码如下:
class Solution(object):
def getAncestors(self, n, edges):
"""
:type n: int
:type edges: List[List[int]]
:rtype: List[List[int]]
"""
# 用邻接矩阵构建图(但将每条边的起点记录在终点后面)
graph = [[] for _ in range(n)]
for from_i, to_i in edges:
graph[to_i].append(from_i)
ans = [[] for _ in range(n)]
for i in range(0, n):
queue = graph[i][:]
while queue: # 队列不为空
x = queue.pop(0) # 队列中弹出第一个元素
ans[i].append(x) # 对应的答案数组中加入x
if x < i:
ans[i].extend(ans[x])
else:
queue.extend(graph[x]) # 队列中加入x的邻接祖先
ans[i] = list(set(ans[i])) # 用集合确保没有重复元素
ans[i].sort()
return ans
运行通过,但超时,卡在第40个例子:
转换思路,使用一个集合vis记录已经访问过的节点,避免重复判断。将判断过程另外定义为一个函数。代码如下:
class Solution(object):
def getAncestors(self, n, edges):
"""
:type n: int
:type edges: List[List[int]]
:rtype: List[List[int]]
"""
# 用邻接列表构造图(记录每个节点的父节点)
graph = [[] for _ in range(n)]
for u, v in edges:
graph[v].append(u)
ans = [[] for _ in range(n)]
def bfs(s): # 对于节点s,找到其所有祖先节点j,向ans[s]中加入节点j
q = deque([s]) # 双端队列记录待搜索的节点,初始化为s节点
vis = {s} # 集合记录已经访问过的节点
while q:
i = q.popleft()
for j in graph[i]:
if j not in vis: # 避免重复访问节点
vis.add(j)
q.append(j)
ans[s].append(j)
ans[s].sort()
for i in range(n):
bfs(i)
return ans
提交通过: