<p>Given the <code>root</code> of a binary tree, replace the value of each node in the tree with the <strong>sum of all its cousins&#39; values</strong>.</p>

<p>Two nodes of a binary tree are <strong>cousins</strong> if they have the same depth with different parents.</p>

<p>Return <em>the </em><code>root</code><em> of the modified tree</em>.</p>

<p><strong>Note</strong> that the depth of a node is the number of edges in the path from the root node to it.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2023/01/11/example11.png" style="width: 571px; height: 151px;" />
<pre>
<strong>Input:</strong> root = [5,4,9,1,10,null,7]
<strong>Output:</strong> [0,0,0,7,7,null,11]
<strong>Explanation:</strong> 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.
</pre>

<p><strong class="example">Example 2:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2023/01/11/diagram33.png" style="width: 481px; height: 91px;" />
<pre>
<strong>Input:</strong> root = [3,1,2]
<strong>Output:</strong> [0,0,0]
<strong>Explanation:</strong> 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.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li>The number of nodes in the tree is in the range <code>[1, 10<sup>5</sup>]</code>.</li>
	<li><code>1 &lt;= Node.val &lt;= 10<sup>4</sup></code></li>
</ul>

# 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]:
        if root is None:
            return root 
        current_height = 1
        # we can only have one root so in this case we can 
        # preemptly close off
        
        # we will need to work with a dictionary 
        # because we 
        queue = {}
        queue[root] = None
        current_level = {} # we want to be able to search in a O(1) way 
        # in this way we will have lenght of the tree as the time complexity
        next_level = {}

        node_list = list(queue.keys())
        while len(node_list) > 0:
            node = node_list.pop(0)
            parent = queue[node]
            # now we can start explorting on the level 
            # of the values
            current_level[node] = parent

            if node.left is not None: 
                next_level[node.left] = node
            if node.right is not None:
                next_level[node.right] = node

            if len(node_list) == 0:
                if current_height > 2:
                    # first building out all the sums at this level
                    current_level_sum = 0
                    current_level_parents_sum = defaultdict(int)

                    for node in current_level.keys():
                        parent = current_level[node]
                        value = node.val
                        current_level_sum += value
                        current_level_parents_sum[parent] += value

                    for node in current_level.keys():
                        parent = current_level[node]
                        node.val = current_level_sum - current_level_parents_sum[parent]

                else:
                    for node in current_level.keys():
                        node.val = 0

                # Updating of all the information
                current_level = {} 
                queue = next_level
                node_list = list(queue.keys())
                next_level = {}
                current_height += 1

        return root
727