Mutating counts without cleanup
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Move from brute-force thinking to an efficient approach using hash map strategy.
Given the root of a binary tree, replace the value of each node in the tree with the sum of all its cousins' values.
Two nodes of a binary tree are cousins if they have the same depth with different parents.
Return the root of the modified tree.
Note that the depth of a node is the number of edges in the path from the root node to it.
Example 1:
Input: root = [5,4,9,1,10,null,7] Output: [0,0,0,7,7,null,11] Explanation: The diagram above shows the initial binary tree and the binary tree after changing the value of each node. - Node with value 5 does not have any cousins so its sum is 0. - Node with value 4 does not have any cousins so its sum is 0. - Node with value 9 does not have any cousins so its sum is 0. - Node with value 1 has a cousin with value 7 so its sum is 7. - Node with value 10 has a cousin with value 7 so its sum is 7. - Node with value 7 has cousins with values 1 and 10 so its sum is 11.
Example 2:
Input: root = [3,1,2] Output: [0,0,0] Explanation: The diagram above shows the initial binary tree and the binary tree after changing the value of each node. - Node with value 3 does not have any cousins so its sum is 0. - Node with value 1 does not have any cousins so its sum is 0. - Node with value 2 does not have any cousins so its sum is 0.
Constraints:
[1, 105].1 <= Node.val <= 104Problem summary: Given the root of a binary tree, replace the value of each node in the tree with the sum of all its cousins' values. Two nodes of a binary tree are cousins if they have the same depth with different parents. Return the root of the modified tree. Note that the depth of a node is the number of edges in the path from the root node to it.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Hash Map · Tree
[5,4,9,1,10,null,7]
[3,1,2]
cousins-in-binary-tree)maximum-level-sum-of-a-binary-tree)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #2641: Cousins in Binary Tree II
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
private List<Integer> s = new ArrayList<>();
public TreeNode replaceValueInTree(TreeNode root) {
dfs1(root, 0);
root.val = 0;
dfs2(root, 0);
return root;
}
private void dfs1(TreeNode root, int depth) {
if (root == null) {
return;
}
if (s.size() <= depth) {
s.add(0);
}
s.set(depth, s.get(depth) + root.val);
dfs1(root.left, depth + 1);
dfs1(root.right, depth + 1);
}
private void dfs2(TreeNode root, int depth) {
int l = root.left == null ? 0 : root.left.val;
int r = root.right == null ? 0 : root.right.val;
int sub = l + r;
++depth;
if (root.left != null) {
root.left.val = s.get(depth) - sub;
dfs2(root.left, depth);
}
if (root.right != null) {
root.right.val = s.get(depth) - sub;
dfs2(root.right, depth);
}
}
}
// Accepted solution for LeetCode #2641: Cousins in Binary Tree II
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func replaceValueInTree(root *TreeNode) *TreeNode {
s := []int{}
var dfs1 func(*TreeNode, int)
dfs1 = func(root *TreeNode, depth int) {
if root == nil {
return
}
if len(s) <= depth {
s = append(s, 0)
}
s[depth] += root.Val
dfs1(root.Left, depth+1)
dfs1(root.Right, depth+1)
}
var dfs2 func(*TreeNode, int)
dfs2 = func(root *TreeNode, depth int) {
l, r := 0, 0
if root.Left != nil {
l = root.Left.Val
}
if root.Right != nil {
r = root.Right.Val
}
sub := l + r
depth++
if root.Left != nil {
root.Left.Val = s[depth] - sub
dfs2(root.Left, depth)
}
if root.Right != nil {
root.Right.Val = s[depth] - sub
dfs2(root.Right, depth)
}
}
dfs1(root, 0)
root.Val = 0
dfs2(root, 0)
return root
}
# Accepted solution for LeetCode #2641: Cousins in Binary Tree II
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def replaceValueInTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
def dfs1(root: Optional[TreeNode], depth: int):
if root is None:
return
if len(s) <= depth:
s.append(0)
s[depth] += root.val
dfs1(root.left, depth + 1)
dfs1(root.right, depth + 1)
def dfs2(root: Optional[TreeNode], depth: int):
sub = (root.left.val if root.left else 0) + (
root.right.val if root.right else 0
)
depth += 1
if root.left:
root.left.val = s[depth] - sub
dfs2(root.left, depth)
if root.right:
root.right.val = s[depth] - sub
dfs2(root.right, depth)
s = []
dfs1(root, 0)
root.val = 0
dfs2(root, 0)
return root
// Accepted solution for LeetCode #2641: Cousins in Binary Tree II
/**
* [2641] Cousins in Binary Tree II
*/
pub struct Solution {}
use crate::util::tree::{to_tree, TreeNode};
// submission codes start here
// Definition for a binary tree node.
// #[derive(Debug, PartialEq, Eq)]
// pub struct TreeNode {
// pub val: i32,
// pub left: Option<Rc<RefCell<TreeNode>>>,
// pub right: Option<Rc<RefCell<TreeNode>>>,
// }
//
// impl TreeNode {
// #[inline]
// pub fn new(val: i32) -> Self {
// TreeNode {
// val,
// left: None,
// right: None
// }
// }
// }
use std::cell::RefCell;
use std::rc::Rc;
impl Solution {
pub fn replace_value_in_tree(
root: Option<Rc<RefCell<TreeNode>>>,
) -> Option<Rc<RefCell<TreeNode>>> {
let root = if let Some(r) = root {
r
} else {
return None;
};
let mut queue = Vec::new();
queue.push(Rc::clone(&root));
while !queue.is_empty() {
let mut next_queue = Vec::new();
let mut sum = 0;
for node in &queue {
if let Some(left) = &node.borrow().left {
next_queue.push(Rc::clone(left));
sum += left.borrow().val;
}
if let Some(right) = &node.borrow().right {
next_queue.push(Rc::clone(right));
sum += right.borrow().val;
}
}
for node in &queue {
let mut children = 0;
if let Some(left) = &node.borrow().left {
children += left.borrow().val;
}
if let Some(right) = &node.borrow().right {
children += right.borrow().val;
}
if let Some(left) = &node.borrow().left {
left.borrow_mut().val = sum - children;
}
if let Some(right) = &node.borrow().right {
right.borrow_mut().val = sum - children;
}
}
queue = next_queue;
}
root.borrow_mut().val = 0;
Some(root)
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_2641() {
assert_eq!(
Solution::replace_value_in_tree(to_tree(vec![
Some(5),
Some(4),
Some(9),
Some(1),
Some(10),
None,
Some(7)
])),
to_tree(vec![
Some(0),
Some(0),
Some(0),
Some(7),
Some(7),
None,
Some(11)
])
);
}
}
// Accepted solution for LeetCode #2641: Cousins in Binary Tree II
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/
function replaceValueInTree(root: TreeNode | null): TreeNode | null {
const s: number[] = [];
const dfs1 = (root: TreeNode | null, depth: number) => {
if (!root) {
return;
}
if (s.length <= depth) {
s.push(0);
}
s[depth] += root.val;
dfs1(root.left, depth + 1);
dfs1(root.right, depth + 1);
};
const dfs2 = (root: TreeNode | null, depth: number) => {
const sub = (root.left?.val || 0) + (root.right?.val || 0);
++depth;
if (root.left) {
root.left.val = s[depth] - sub;
dfs2(root.left, depth);
}
if (root.right) {
root.right.val = s[depth] - sub;
dfs2(root.right, depth);
}
};
dfs1(root, 0);
root.val = 0;
dfs2(root, 0);
return root;
}
Use this to step through a reusable interview workflow for this problem.
BFS with a queue visits every node exactly once — O(n) time. The queue may hold an entire level of the tree, which for a complete binary tree is up to n/2 nodes = O(n) space. This is optimal in time but costly in space for wide trees.
Every node is visited exactly once, giving O(n) time. Space depends on tree shape: O(h) for recursive DFS (stack depth = height h), or O(w) for BFS (queue width = widest level). For balanced trees h = log n; for skewed trees h = n.
Review these before coding to avoid predictable interview regressions.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Wrong move: Recursive traversal assumes children always exist.
Usually fails on: Leaf nodes throw errors or create wrong depth/path values.
Fix: Handle null/base cases before recursive transitions.