这是我参与11月更文挑战的第8天,活动详情查看2021最后一次更文挑战
链接
周赛一共四道题,今天是后两道题的解析。
题目
2049. 统计最高分的节点数目
DFS
解析
二叉树的题大多会和dfs/bfs有关,bfs也就是层序遍历,具体节点的dfs遍历方式可以分为先序、中序、后序遍历三种。这道题要求的最大得分抽象出来其实就是对后序遍历时遍历到每个节点时,节点的左子树元素个数、右子树元素个数、和剩下元素的个数三者计算得出的结果与一个最大值去相比并更新它。
还有两点要注意的是,首先最大得分的计算方法与左子树元素个数、右子树元素个数和剩下元素个数有关,一共可以分成5种情况,具体见代码。第二点是最大得分与最大得分个数的关系,实际上求最大得分个数的逻辑很简单,即另外用一个变量保存最大得分个数,每次出现新的最大得分时置这个变量为1,每次出现相同的最大得分时将这个变量加1。
代码
class Solution:
def countHighestScoreNodes(self, parents: List[int]) -> int:
n = len(parents)
nodes = [[None, None] for _ in range(0, n)]
for i in range(1, n):
parent = parents[i]
if nodes[parent][0] is None:
nodes[parent][0] = i
else:
nodes[parent][1] = i
self.nodes = nodes
self.n = n
self.maxScore, self.maxScoreCount = 1, 0
self.childNumCount(0)
return self.maxScoreCount
def childNumCount(self, nodeInd):
if self.nodes[nodeInd][0] == None:
self.countScore(self.n-1)
return 1
elif self.nodes[nodeInd][1] == None:
leftChildNumCount = self.childNumCount(self.nodes[nodeInd][0])
elseCount = self.n-1 - leftChildNumCount
if elseCount == 0:
score = leftChildNumCount
else:
score = elseCount * leftChildNumCount
self.countScore(score)
return 1 + leftChildNumCount
else:
leftChildNumCount = self.childNumCount(self.nodes[nodeInd][0])
rightChildNumCount = self.childNumCount(self.nodes[nodeInd][1])
elseCount = self.n-1 - leftChildNumCount - rightChildNumCount
if elseCount == 0:
score = leftChildNumCount * rightChildNumCount
else:
score = elseCount * leftChildNumCount * rightChildNumCount
self.countScore(score)
return 1 + leftChildNumCount + rightChildNumCount
def countScore(self, score):
if score > self.maxScore:
self.maxScore = score
self.maxScoreCount = 1
elif score == self.maxScore:
self.maxScoreCount += 1
2050. 并行课程 III
拓扑排序+基础DP
解析
这道题的描述与LeetCode常见的207. 课程表、210. 课程表 II这两道题十分类似,容易想到用拓扑排序的思想来对课程排序。唯一的区别是要求所有课程完成的最少时间。
基于贪心的思想,如果“每一门课程都尽可能早的完成”,那在题中这样一个有向无环图中所有的课程都会在其可能的最早时间完成,也就相当于求出了所有课程的最少完成时间。上述描述也等价于一个具有拓扑排序关系的有向无环图中,所有课程只需要在其最晚前置课程完成后马上开始修读即可,以一个dp数组来存储这个最晚时间,然后拓扑排序完成后遍历这个数组,即可求出所有课程的最晚完成时间。
代码
class Solution:
def minimumTime(self, n: int, relations: List[List[int]], time: List[int]) -> int:
latestTime = [time[i] for i in range(0, n)]
if len(relations) == 0:
return max(time)
adj = [[] for _ in range(n)]
relationCount = len(relations)
indegree = [0] * n
for relation in relations:
adj[relation[0]-1].append(relation[1]-1)
indegree[relation[1]-1] += 1
queue = []
for i in range(n):
if indegree[i] == 0:
queue.append(i)
while len(queue):
front = queue.pop(0)
for tail in adj[front]:
latestTime[tail] = max(latestTime[tail], latestTime[front] + time[tail])
indegree[tail] -= 1
relationCount -= 1
if indegree[tail] == 0:
queue.append(tail)
return max(latestTime)