2458-移除子树后的二叉树高度

Raphael Liu Lv10

给你一棵 二叉树 的根节点 root ,树中有 n 个节点。每个节点都可以被分配一个从 1n 且互不相同的值。另给你一个长度为
m 的数组 queries

你必须在树上执行 m独立 的查询,其中第 i 个查询你需要执行以下操作:

  • 从树中 移除queries[i] 的值作为根节点的子树。题目所用测试用例保证 queries[i] 等于根节点的值。

返回一个长度为 m 的数组 __answer __ ,其中 __answer[i] __ 是执行第 i 个查询后树的高度。

注意:

  • 查询之间是独立的,所以在每个查询执行后,树会回到其 初始 状态。
  • 树的高度是从根到树中某个节点的 最长简单路径中的边数

示例 1:

**输入:** root = [1,3,4,2,null,6,5,null,null,null,null,null,7], queries = [4]
**输出:** [2]
**解释:** 上图展示了从树中移除以 4 为根节点的子树。
树的高度是 2(路径为 1 -> 3 -> 2)。

示例 2:

**输入:** root = [5,8,9,2,1,3,7,4,6], queries = [3,2,4,8]
**输出:** [3,2,3,2]
**解释:** 执行下述查询:
- 移除以 3 为根节点的子树。树的高度变为 3(路径为 5 -> 8 -> 2 -> 4)。
- 移除以 2 为根节点的子树。树的高度变为 2(路径为 5 -> 8 -> 1)。
- 移除以 4 为根节点的子树。树的高度变为 3(路径为 5 -> 8 -> 2 -> 6)。
- 移除以 8 为根节点的子树。树的高度变为 2(路径为 5 -> 9 -> 3)。

提示:

  • 树中节点的数目是 n
  • 2 <= n <= 105
  • 1 <= Node.val <= n
  • 树中的所有值 互不相同
  • m == queries.length
  • 1 <= m <= min(n, 104)
  • 1 <= queries[i] <= n
  • queries[i] != root.val

如果真的模拟删除子树去解题,那么对每个query,需要遍历一遍树的所有节点,复杂度为*O(MN)*。为此我们可以先统计所有子树的高度。

1. 使用DFS对每个节点进行统计

1
2
3
4
5
6
7
8
    unordered_map<TreeNode*, int> height;
## int computeHeight(TreeNode* root) {
if (!root) {
return 0;
}
height[root] = 1 + max(computeHeight(root->left), computeHeight(root->right));
return height[root];
}

2. 假设在某个节点node,已知其深度(即根节点root到node的距离)以及删除node后剩余的树的高度*res[node]*,那么删除其左子树node->left后剩余的树的高度为:

1. node的右子树的高度height[node->right]与node深度depth之和
2. 删除node后设关于的树的高度res[node]

两者中的较大值,删除右子树同理。

使用DFS:

1
2
3
4
5
6
7
8
9
void dfs(TreeNode* root, int depth, int rest) {
if (!root) {
return;
}
depth++;
res[root->val] = rest;
dfs(root->left, depth, max(depth + height[root->right], rest));
dfs(root->right, depth, max(depth + height[root->left], rest));
}

使用BFS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void bfs(TreeNode* root) {
if (!root) {
return;
}
queue<pair<TreeNode*, int>> que;
que.push(make_pair(root, 0));
while (!que.empty()) {
TreeNode* curr = que.front().first;
int depth = que.front().second;
que.pop();
if (curr->left) {
res[curr->left->val] = max(res[curr->val], height[curr->right] + depth);
que.push(make_pair(curr->left, depth + 1));
}
if (curr->right) {
res[curr->right->val] = max(res[curr->val], height[curr->left] + depth);
que.push(make_pair(curr->right, depth + 1));
}
}
}

最后实现:

1
2
3
4
5
6
7
8
9
vector<int> treeQueries(TreeNode* root, vector<int>& queries) {
computeHeight(root);
// dfs(root, -1, 0);
bfs(root);
for (auto& q : queries) {
q = res[q];
}
return queries;
}

时间复杂度:DFS或者BFS的时间复杂度均为O(N),故总体的复杂度为O(N)。
空间复杂度:对每个节点都需要空间来存储其高度和删除节点后剩余子树的高度,故复杂度为O(N)。

 Comments