📅  最后修改于: 2023-12-03 15:06:20.111000             🧑  作者: Mango
在二叉树的顶视图中,我们只看到树中的最左边和最右边的节点以及它们之间的边,因此形成了一种视觉上的顶视图。
现在给出一个二叉树,请计算它的顶视图中所有节点的值之和。
为了计算顶视图中的节点总和,我们需要找到顶视图中每一列中的最左边的节点和最右边的节点,然后对它们进行求和。
为了找到每一列中的最左边和最右边的节点,我们使用广度优先搜索。我们首先将根节点入队列,然后在队列中进行广度优先搜索,每当我们遇到一个新的节点时,我们将其放入队列的末尾。每当我们遍历队列中的节点时,我们记录它们所在的列数。如果当前节点是该列的第一个节点,则它是该列的最左边的节点;如果当前节点是该列的最后一个节点,则它是该列的最右边的节点。
最后,我们将所有最左边的节点和最右边的节点的值相加,就得到了顶视图中所有节点的值之和。
下面是Java语言的解法实现:
class Solution {
public int topViewSum(TreeNode root) {
if (root == null) {
return 0;
}
int left = 0, right = 0;
Map<Integer, Integer> leftMap = new HashMap<>(); // 记录每一列中最左边的节点的值
Map<Integer, Integer> rightMap = new HashMap<>(); // 记录每一列中最右边的节点的值
Queue<TreeNode> queue = new LinkedList<>(); // 广度优先搜索队列
Queue<Integer> columnQueue = new LinkedList<>(); // 记录每个节点所在的列数的队列
queue.offer(root); // 将根节点入队列
columnQueue.offer(0); // 根节点所在的列数为0
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
int column = columnQueue.poll();
if (!leftMap.containsKey(column)) {
leftMap.put(column, node.val); // 如果是该列的第一个节点,则记录最左边的节点的值
}
rightMap.put(column, node.val); // 记录最右边的节点的值
if (node.left != null) {
queue.offer(node.left);
columnQueue.offer(column - 1); // 左节点的列数为当前节点的列数减1
}
if (node.right != null) {
queue.offer(node.right);
columnQueue.offer(column + 1); // 右节点的列数为当前节点的列数加1
}
}
}
for (int column : leftMap.keySet()) {
left += leftMap.get(column); // 计算最左边的节点的值之和
}
for (int column : rightMap.keySet()) {
right += rightMap.get(column); // 计算最右边的节点的值之和
}
return left + right - root.val; // 计算顶视图中所有节点的值之和(需要减去根节点的值)
}
}
该算法的时间复杂度为$O(n)$,其中$n$是二叉树中节点的数量。我们需要对每个节点进行一次广度优先搜索,每次广度优先搜索的时间复杂度为$O(1)$,因此总的时间复杂度为$O(n)$。
该算法的空间复杂度为$O(n)$。我们需要使用一个队列和两个哈希表来存储节点和记录每一列中的最左边和最右边的节点,因此总的空间复杂度为$O(n)$。