|
| 1 | +--- |
| 2 | +id: Count-Nodes-Equal-to-Average-of-Subtree |
| 3 | +title: Count Nodes Equal to Average of Subtree |
| 4 | +sidebar_label: 2265-Count Nodes Equal to Average of Subtree |
| 5 | +tags: |
| 6 | + - Arrays |
| 7 | + - Brute Force |
| 8 | + - Optimized approach |
| 9 | + - LeetCode |
| 10 | + - Python |
| 11 | + - Java |
| 12 | + - C++ |
| 13 | + |
| 14 | +description: "This is a solution to Count Nodes Equal to Average of Subtree problem on LeetCode." |
| 15 | +sidebar_position: 66 |
| 16 | +--- |
| 17 | + |
| 18 | +## Problem Statement |
| 19 | +In this tutorial, we will solve the Count Nodes Equal to Average of Subtree problem . We will provide the implementation of the solution in Python, Java, and C++. |
| 20 | + |
| 21 | +### Problem Description |
| 22 | + |
| 23 | +Given the root of a binary tree, return the number of nodes where the value of the node is equal to the average of the values in its subtree. |
| 24 | + |
| 25 | +Note: |
| 26 | + |
| 27 | +The average of n elements is the sum of the n elements divided by n and rounded down to the nearest integer. |
| 28 | +A subtree of root is a tree consisting of root and all of its descendants. |
| 29 | + |
| 30 | +### Examples |
| 31 | + |
| 32 | +**Example 1:** |
| 33 | +Input: root = [4,8,5,0,1,null,6] |
| 34 | +Output: 5 |
| 35 | +Explanation: |
| 36 | +For the node with value 4: The average of its subtree is (4 + 8 + 5 + 0 + 1 + 6) / 6 = 24 / 6 = 4. |
| 37 | +For the node with value 5: The average of its subtree is (5 + 6) / 2 = 11 / 2 = 5. |
| 38 | +For the node with value 0: The average of its subtree is 0 / 1 = 0. |
| 39 | +For the node with value 1: The average of its subtree is 1 / 1 = 1. |
| 40 | +For the node with value 6: The average of its subtree is 6 / 1 = 6. |
| 41 | +**Example 2:** |
| 42 | +Input: root = [1] |
| 43 | +Output: 1 |
| 44 | +Explanation: For the node with value 1: The average of its subtree is 1 / 1 = 1. |
| 45 | + |
| 46 | +### Constraints |
| 47 | +- `The number of nodes in the tree is in the range [1, 1000].` |
| 48 | +- `0 <= Node.val <= 1000` |
| 49 | + |
| 50 | +## Solution of Given Problem |
| 51 | + |
| 52 | +### Intuition and Approach |
| 53 | + |
| 54 | +The problem can be solved using a brute force approach or an optimized Technique. |
| 55 | + |
| 56 | +<Tabs> |
| 57 | +<tabItem value="Brute Force" label="Brute Force"> |
| 58 | + |
| 59 | +### Approach 1:Brute Force (Naive) |
| 60 | + |
| 61 | + |
| 62 | +In the brute force approach, we can perform the following steps: |
| 63 | + |
| 64 | +- Traverse each node in the tree. |
| 65 | +- For each node, calculate the sum and count of the nodes in its subtree. |
| 66 | +- Compute the average value of the subtree. |
| 67 | +- Check if the node’s value equals the computed average. |
| 68 | + |
| 69 | +#### Codes in Different Languages |
| 70 | + |
| 71 | +<Tabs> |
| 72 | +<TabItem value="C++" label="C++" default> |
| 73 | +<SolutionAuthor name="@AmruthaPariprolu"/> |
| 74 | + |
| 75 | +```cpp |
| 76 | +#include <iostream> |
| 77 | +#include <vector> |
| 78 | +using namespace std; |
| 79 | + |
| 80 | +struct TreeNode { |
| 81 | + int val; |
| 82 | + TreeNode* left; |
| 83 | + TreeNode* right; |
| 84 | + TreeNode(int x) : val(x), left(NULL), right(NULL) {} |
| 85 | +}; |
| 86 | + |
| 87 | +pair<int, int> subtreeSumCount(TreeNode* root) { |
| 88 | + if (!root) return {0, 0}; |
| 89 | + auto left = subtreeSumCount(root->left); |
| 90 | + auto right = subtreeSumCount(root->right); |
| 91 | + int sum = root->val + left.first + right.first; |
| 92 | + int count = 1 + left.second + right.second; |
| 93 | + return {sum, count}; |
| 94 | +} |
| 95 | + |
| 96 | +int bruteForceCount(TreeNode* root) { |
| 97 | + if (!root) return 0; |
| 98 | + auto [sum, count] = subtreeSumCount(root); |
| 99 | + int average = sum / count; |
| 100 | + int match = (root->val == average) ? 1 : 0; |
| 101 | + return match + bruteForceCount(root->left) + bruteForceCount(root->right); |
| 102 | +} |
| 103 | + |
| 104 | + |
| 105 | +``` |
| 106 | +</TabItem> |
| 107 | +<TabItem value="Java" label="Java"> |
| 108 | +<SolutionAuthor name="@AmruthaPariprolu"/> |
| 109 | +
|
| 110 | +```java |
| 111 | +class TreeNode { |
| 112 | + int val; |
| 113 | + TreeNode left; |
| 114 | + TreeNode right; |
| 115 | + TreeNode(int x) { val = x; } |
| 116 | +} |
| 117 | +
|
| 118 | +class Solution { |
| 119 | + private int[] subtreeSumCount(TreeNode root) { |
| 120 | + if (root == null) return new int[]{0, 0}; |
| 121 | + int[] left = subtreeSumCount(root.left); |
| 122 | + int[] right = subtreeSumCount(root.right); |
| 123 | + int sum = root.val + left[0] + right[0]; |
| 124 | + int count = 1 + left[1] + right[1]; |
| 125 | + return new int[]{sum, count}; |
| 126 | + } |
| 127 | + |
| 128 | + public int bruteForceCount(TreeNode root) { |
| 129 | + if (root == null) return 0; |
| 130 | + int[] res = subtreeSumCount(root); |
| 131 | + int average = res[0] / res[1]; |
| 132 | + int match = (root.val == average) ? 1 : 0; |
| 133 | + return match + bruteForceCount(root.left) + bruteForceCount(root.right); |
| 134 | + } |
| 135 | +} |
| 136 | +
|
| 137 | +
|
| 138 | +``` |
| 139 | + |
| 140 | + |
| 141 | +</TabItem> |
| 142 | +<TabItem value="Python" label="Python"> |
| 143 | +<SolutionAuthor name="@AmruthaPariprolu"/> |
| 144 | + |
| 145 | +```python |
| 146 | +class TreeNode: |
| 147 | + def __init__(self, val=0, left=None, right=None): |
| 148 | + self.val = val |
| 149 | + self.left = left |
| 150 | + self.right = right |
| 151 | + |
| 152 | +def subtree_sum_count(root): |
| 153 | + if not root: |
| 154 | + return (0, 0) |
| 155 | + left = subtree_sum_count(root.left) |
| 156 | + right = subtree_sum_count(root.right) |
| 157 | + subtree_sum = root.val + left[0] + right[0] |
| 158 | + subtree_count = 1 + left[1] + right[1] |
| 159 | + return (subtree_sum, subtree_count) |
| 160 | + |
| 161 | +def brute_force_count(root): |
| 162 | + if not root: |
| 163 | + return 0 |
| 164 | + subtree_sum, subtree_count = subtree_sum_count(root) |
| 165 | + average = subtree_sum // subtree_count |
| 166 | + match = 1 if root.val == average else 0 |
| 167 | + return match + brute_force_count(root.left) + brute_force_count(root.right) |
| 168 | + |
| 169 | +``` |
| 170 | + |
| 171 | +</TabItem> |
| 172 | +</Tabs> |
| 173 | + |
| 174 | + |
| 175 | +### Complexity Analysis |
| 176 | + |
| 177 | +- Time Complexity: $O(n^2)$ |
| 178 | +- For each node, calculate the sum and count of the nodes in its subtree. |
| 179 | +- Compute the average and check if it matches the node’s value. |
| 180 | +- Traverse each node to repeat the above steps. |
| 181 | +- Space Complexity: $O(h)$ |
| 182 | +- where h is the height of the tree due to the recursion stack. |
| 183 | +</tabItem> |
| 184 | +<tabItem value="Optimized approach" label="Optimized approach"> |
| 185 | + |
| 186 | +### Approach 2: Optimized approach |
| 187 | + |
| 188 | +In the optimized approach, we can perform a single post-order traversal to calculate the sum and count of each subtree. During this traversal, we can also check if the current node's value is equal to the average of its subtree. |
| 189 | + |
| 190 | + |
| 191 | +#### Code in Different Languages |
| 192 | + |
| 193 | +<Tabs> |
| 194 | +<TabItem value="C++" label="C++" default> |
| 195 | +<SolutionAuthor name="@AmruthaPariprolu"/> |
| 196 | + |
| 197 | +```cpp |
| 198 | +#include <iostream> |
| 199 | +#include <vector> |
| 200 | +using namespace std; |
| 201 | + |
| 202 | +struct TreeNode { |
| 203 | + int val; |
| 204 | + TreeNode* left; |
| 205 | + TreeNode* right; |
| 206 | + TreeNode(int x) : val(x), left(NULL), right(NULL) {} |
| 207 | +}; |
| 208 | + |
| 209 | +pair<int, int> subtreeSumCount(TreeNode* root, int& count) { |
| 210 | + if (!root) return {0, 0}; |
| 211 | + auto left = subtreeSumCount(root->left, count); |
| 212 | + auto right = subtreeSumCount(root->right, count); |
| 213 | + int sum = root->val + left.first + right.first; |
| 214 | + int nodes = 1 + left.second + right.second; |
| 215 | + if (root->val == sum / nodes) count++; |
| 216 | + return {sum, nodes}; |
| 217 | +} |
| 218 | + |
| 219 | +int optimizedCount(TreeNode* root) { |
| 220 | + int count = 0; |
| 221 | + subtreeSumCount(root, count); |
| 222 | + return count; |
| 223 | +} |
| 224 | + |
| 225 | + |
| 226 | + |
| 227 | +``` |
| 228 | +</TabItem> |
| 229 | +<TabItem value="Java" label="Java"> |
| 230 | +<SolutionAuthor name="@AmruthaPariprolu"/> |
| 231 | +
|
| 232 | +```java |
| 233 | +class TreeNode { |
| 234 | + int val; |
| 235 | + TreeNode left; |
| 236 | + TreeNode right; |
| 237 | + TreeNode(int x) { val = x; } |
| 238 | +} |
| 239 | +
|
| 240 | +class Solution { |
| 241 | + private int[] subtreeSumCount(TreeNode root, int[] count) { |
| 242 | + if (root == null) return new int[]{0, 0}; |
| 243 | + int[] left = subtreeSumCount(root.left, count); |
| 244 | + int[] right = subtreeSumCount(root.right, count); |
| 245 | + int sum = root.val + left[0] + right[0]; |
| 246 | + int nodes = 1 + left[1] + right[1]; |
| 247 | + if (root.val == sum / nodes) count[0]++; |
| 248 | + return new int[]{sum, nodes}; |
| 249 | + } |
| 250 | + |
| 251 | + public int optimizedCount(TreeNode root) { |
| 252 | + int[] count = new int[1]; |
| 253 | + subtreeSumCount(root, count); |
| 254 | + return count[0]; |
| 255 | + } |
| 256 | +} |
| 257 | +
|
| 258 | +``` |
| 259 | + |
| 260 | + |
| 261 | +</TabItem> |
| 262 | +<TabItem value="Python" label="Python"> |
| 263 | +<SolutionAuthor name="@AmruthaPariprolu"/> |
| 264 | + |
| 265 | +```python |
| 266 | +class TreeNode: |
| 267 | + def __init__(self, val=0, left=None, right=None): |
| 268 | + self.val = val |
| 269 | + self.left = left |
| 270 | + self.right = right |
| 271 | + |
| 272 | +def subtree_sum_count(root, count): |
| 273 | + if not root: |
| 274 | + return (0, 0) |
| 275 | + left = subtree_sum_count(root.left, count) |
| 276 | + right = subtree_sum_count(root.right, count) |
| 277 | + subtree_sum = root.val + left[0] + right[0] |
| 278 | + subtree_count = 1 + left[1] + right[1] |
| 279 | + if root.val == subtree_sum // subtree_count: |
| 280 | + count[0] += 1 |
| 281 | + return (subtree_sum, subtree_count) |
| 282 | + |
| 283 | +def optimized_count(root): |
| 284 | + count = [0] |
| 285 | + subtree_sum_count(root, count) |
| 286 | + return count[0] |
| 287 | + |
| 288 | + |
| 289 | +``` |
| 290 | + |
| 291 | +</TabItem> |
| 292 | +</Tabs> |
| 293 | + |
| 294 | +#### Complexity Analysis |
| 295 | + |
| 296 | +- Time Complexity: $O(n)$ |
| 297 | +- Perform a single post-order traversal to compute the sum and count of each subtree. |
| 298 | +- Check if the current node's value matches the average of its subtree during the traversal. |
| 299 | +- Use the results of the traversal to count matching nodes. |
| 300 | +- Space Complexity: $O(h)$ |
| 301 | + |
| 302 | +- where h is the height of the tree due to the recursion stack. |
| 303 | + |
| 304 | +</tabItem> |
| 305 | +</Tabs> |
| 306 | + |
| 307 | +--- |
| 308 | + |
| 309 | +<h2>Authors:</h2> |
| 310 | + |
| 311 | +<div style={{display: 'flex', flexWrap: 'wrap', justifyContent: 'space-between', gap: '10px'}}> |
| 312 | +{['AmruthaPariprolu'].map(username => ( |
| 313 | + <Author key={username} username={username} /> |
| 314 | +))} |
| 315 | +</div> |
0 commit comments