# 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 maxAncestorDiff(self, root: TreeNode) -> int:
def helper(node, cur_min, cur_max):
if not node:
return cur_max - cur_min
cur_min = min(cur_min, node.val)
cur_max = max(cur_max, node.val)
left = helper(node.left, cur_min, cur_max)
right = helper(node.right, cur_min, cur_max)
return max(left, right)
return helper(root, root.val, root.val)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int helper(TreeNode* node, int cur_min, int cur_max) {
if (!node) return cur_max - cur_min;
cur_min = std::min(cur_min, node->val);
cur_max = std::max(cur_max, node->val);
int left = helper(node->left, cur_min, cur_max);
int right = helper(node->right, cur_min, cur_max);
return std::max(left, right);
}
int maxAncestorDiff(TreeNode* root) {
return helper(root, root->val, root->val);
}
};
/**
* 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 {
public int maxAncestorDiff(TreeNode root) {
return helper(root, root.val, root.val);
}
private int helper(TreeNode node, int curMin, int curMax) {
if (node == null) return curMax - curMin;
curMin = Math.min(curMin, node.val);
curMax = Math.max(curMax, node.val);
int left = helper(node.left, curMin, curMax);
int right = helper(node.right, curMin, curMax);
return Math.max(left, right);
}
}
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
var maxAncestorDiff = function(root) {
function helper(node, curMin, curMax) {
if (!node) return curMax - curMin;
curMin = Math.min(curMin, node.val);
curMax = Math.max(curMax, node.val);
let left = helper(node.left, curMin, curMax);
let right = helper(node.right, curMin, curMax);
return Math.max(left, right);
}
return helper(root, root.val, root.val);
};
You are given the root of a binary tree. For each node in the tree, consider the difference between that node's value and the values of all its ancestor nodes. Your task is to find the maximum such difference across the entire tree.
val
), and pointers to left and right children.
To solve this problem, we need to compare each node's value with all of its ancestors. The brute-force way would be, for every node, to walk up its ancestor path and compute the difference with each ancestor. However, this would be inefficient because it could lead to repeated computations and a lot of redundant traversals.
Instead, we can notice that as we traverse from the root to any node, we can keep track of the minimum and maximum values seen so far along the path. For any current node, the largest possible difference with its ancestors is the maximum of:
We will use a Depth-First Search (DFS) traversal of the tree, passing down the minimum and maximum values found along the path from the root to the current node. Here’s how the algorithm works step-by-step:
This approach ensures that each node is visited only once, and the minimum and maximum values are efficiently propagated down the tree without redundant computations.
Let's consider the following binary tree:
8 / \ 3 10 / \ \ 1 6 14 / \ / 4 7 13
We start at the root (8), so both min and max are 8.
The maximum difference found is 7 (between node 1 and ancestor 8).
By keeping track of the minimum and maximum values along the path from the root to each node, we can efficiently compute the maximum difference between any node and its ancestors in a single traversal. This approach avoids redundant calculations and leverages the properties of depth-first search to achieve optimal time and space complexity. The key insight is propagating state (min/max) down the tree, so every node knows the range of its ancestors without explicitly storing ancestor lists.