Medium
题目描述
给你一棵二叉树的根 root ,请你将每个节点的值替换为该节点的所有表兄弟节点值的和。
如果两个节点在树中有相同的深度且它们的父节点不同,则它们互为表兄弟。
返回修改后树的根。
注意:节点的深度是从根节点到该节点的路径中边的数目。
示例 1:
输入:root = [5,4,9,1,10,null,7]
输出:[0,0,0,7,7,null,11]
解释:上图展示了初始的二叉树和修改每个节点的值之后的二叉树。
- 节点值为 5 的节点没有表兄弟,所以其和为 0 。
- 节点值为 4 的节点没有表兄弟,所以其和为 0 。
- 节点值为 9 的节点没有表兄弟,所以其和为 0 。
- 节点值为 1 的节点有一个表兄弟,值为 7 ,所以其和为 7 。
- 节点值为 10 的节点有一个表兄弟,值为 7 ,所以其和为 7 。
- 节点值为 7 的节点有两个表兄弟,值分别为 1 和 10 ,所以其和为 11 。
示例 2:
输入:root = [3,1,2]
输出:[0,0,0]
解释:上图展示了初始的二叉树和修改每个节点的值之后的二叉树。
- 节点值为 3 的节点没有表兄弟,所以其和为 0 。
- 节点值为 1 的节点没有表兄弟,所以其和为 0 。
- 节点值为 2 的节点没有表兄弟,所以其和为 0 。
提示:
- 树中节点数目在范围
[1, 10^5]内。 1 <= Node.val <= 10^4
解题思路
解题思路
这道题的关键在于理解表兄弟节点的定义:同一层的不同父节点的子节点。
解决这个问题需要两次遍历:
第一次遍历:计算每一层的节点值总和。我们可以使用BFS层序遍历,记录每一层所有节点的值之和。
第二次遍历:更新每个节点的值。对于每个节点,其新值 = 当前层的总和 - 兄弟节点的值之和。这里的兄弟节点指的是同一个父节点的所有子节点。
具体实现步骤:
- 第一次BFS遍历,用数组记录每层的节点值总和
- 第二次BFS遍历,对于每个节点的子节点们:
- 计算子节点们的值之和(兄弟节点和)
- 每个子节点的新值 = 下一层总和 - 兄弟节点和
- 根节点没有表兄弟,直接设为0
这种方法的优势在于思路清晰,易于理解和实现。时间复杂度为O(n),空间复杂度为O(n),其中n是树中节点的数量。
代码实现
class Solution {
public:
TreeNode* replaceValueInTree(TreeNode* root) {
if (!root) return root;
// 第一次BFS:计算每层的总和
vector<int> levelSum;
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
int size = q.size();
int sum = 0;
for (int i = 0; i < size; i++) {
TreeNode* node = q.front();
q.pop();
sum += node->val;
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
levelSum.push_back(sum);
}
// 第二次BFS:更新节点值
q.push(root);
root->val = 0; // 根节点没有表兄弟
int level = 0;
while (!q.empty()) {
int size = q.size();
for (int i = 0; i < size; i++) {
TreeNode* node = q.front();
q.pop();
// 计算子节点的兄弟节点和
int siblingSum = 0;
if (node->left) siblingSum += node->left->val;
if (node->right) siblingSum += node->right->val;
// 更新子节点值
if (node->left) {
node->left->val = levelSum[level + 1] - siblingSum;
q.push(node->left);
}
if (node->right) {
node->right->val = levelSum[level + 1] - siblingSum;
q.push(node->right);
}
}
level++;
}
return root;
}
};
class Solution:
def replaceValueInTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if not root:
return root
# 第一次BFS:计算每层的总和
level_sum = []
queue = [root]
while queue:
current_sum = 0
next_queue = []
for node in queue:
current_sum += node.val
if node.left:
next_queue.append(node.left)
if node.right:
next_queue.append(node.right)
level_sum.append(current_sum)
queue = next_queue
# 第二次BFS:更新节点值
queue = [root]
root.val = 0 # 根节点没有表兄弟
level = 0
while queue:
next_queue = []
for node in queue:
# 计算子节点的兄弟节点和
sibling_sum = 0
if node.left:
sibling_sum += node.left.val
if node.right:
sibling_sum += node.right.val
# 更新子节点值
if node.left:
node.left.val = level_sum[level + 1] - sibling_sum
next_queue.append(node.left)
if node.right:
node.right.val = level_sum[level + 1] - sibling_sum
next_queue.append(node.right)
queue = next_queue
level += 1
return root
public class Solution {
public TreeNode ReplaceValueInTree(TreeNode root) {
if (root == null) return root;
// 第一次BFS:计算每层的总和
List<int> levelSum = new List<int>();
Queue<TreeNode> queue = new Queue<TreeNode>();
queue.Enqueue(root);
while (queue.Count > 0) {
int size = queue.Count;
int sum = 0;
for (int i = 0; i < size; i++) {
TreeNode node = queue.Dequeue();
sum += node.val;
if (node.left != null) queue.Enqueue(node.left);
if (node.right != null) queue.Enqueue(node.right);
}
levelSum.Add(sum);
}
// 第二次BFS:更新节点值
queue.Enqueue(root);
root.val = 0; // 根节点没有表兄弟
int level = 0;
while (queue.Count > 0) {
int size = queue.Count;
for (int i = 0; i < size; i++) {
TreeNode node = queue.Dequeue();
// 计算子节点的兄弟节点和
int siblingSum = 0;
if (node.left != null) siblingSum += node.left.val;
if (node.right != null) siblingSum += node.right.val;
// 更新子节点值
if (node.left != null) {
node.left.val = levelSum[level + 1] - siblingSum;
queue.Enqueue(node.left);
}
if (node.right != null) {
node.right.val = levelSum[level + 1] - siblingSum;
queue.Enqueue(node.right);
}
}
level++;
}
return root;
}
}
var replaceValueInTree = function(root) {
if (!root) return root;
// 第一次BFS:计算每层的总和
const levelSum = [];
let queue = [root];
while (queue.length > 0) {
let sum = 0;
const nextQueue = [];
for (const node of queue) {
sum += node.val;
if (node.left) nextQueue.push(node.left);
if (node.right) nextQueue.push(node.right);
}
levelSum.push(sum);
queue = nextQueue;
}
// 第二次BFS:更新节点值
queue = [root];
root.val = 0; // 根节点没有表兄弟
let level = 0;
while (queue.length > 0) {
const nextQueue = [];
for (const node of queue) {
// 计算子节点的兄弟节点和
let siblingSum = 0;
if (node.left) siblingSum += node.left.val;
if (node.right) siblingSum += node.right.val;
// 更新子节点值
if (node.left) {
node.left.val = levelSum[level + 1] - siblingSum;
nextQueue.push(node.left);
}
if (node.right) {
node.right.val = levelSum[level + 1] - siblingSum;
nextQueue.push(node.right);
}
}
queue = nextQueue;
level++;
}
return root;
};
复杂度分析
| 复杂度类型 | 值 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 需要遍历所有节点两次,每个节点的操作都是常数时间 |
| 空间复杂度 | O(n) | 队列最多存储一层的节点,最坏情况下为O(n);levelSum数组存储每层和,最多O(log n)层 |
相关题目
. Cousins in Binary Tree (Easy)
. Maximum Level Sum of a Binary Tree (Medium)