How does it ensure that one node is an ancestor and not a sibling?

J. Doe :

I am trying to solve this LeetCode question:

Given the root of a binary tree, find the maximum value V for which there exists different nodes A and B where V = |A.val - B.val| and A is an ancestor of B. (A node A is an ancestor of B if either: any child of A is equal to B, or any child of A is an ancestor of B.)

One of the highly upvoted answers is as below:

public int maxAncestorDiff(TreeNode root) {
    return dfs(root, root.val, root.val);
}

public int dfs(TreeNode root, int mn, int mx) {
    if (root == null) return mx - mn;
    mx = Math.max(mx, root.val);
    mn = Math.min(mn, root.val);
    return Math.max(dfs(root.left, mn, mx), dfs(root.right, mn, mx));
}

This is basically just a preorder traversal of the tree. I am unable to digest how it ensures that node A is an ancestor of node B (and not a sibling)?

Primusa :

Let's break this down.

You are correct that this is just a pre-order transversal. What's important is that for each node we have a minimum value and a maximum value. These values get smaller and larger respectively as we iterate down the tree. At any one given node, we only update mn and mx with the value of that node. As a result when we pass mn and mx to the children, those values are only reflective of nodes in the tree up to the current node.

Perhaps these comments will illustrate this better:

public int dfs(TreeNode root, int mn, int mx) {

    // this is the base case, at some point mn was encountered and mx was encountered
    // on the path to this node, this is the maximum possible difference along that path
    if (root == null) return mx - mn;

    // on our current path through the tree, update the max / min value we have encountered
    mx = Math.max(mx, root.val);
    mn = Math.min(mn, root.val);

    // the mn and mx at this point are only reflective of this node and it's ancestors
    // integers are immutable so a function call down the line won't change the 
    // mx and mn here, but rather create a new mx and mn at that node
    // we pass the updated mx and mn to the node's children, exploring paths
    // down the tree

    return Math.max(dfs(root.left, mn, mx), dfs(root.right, mn, mx));
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=166791&siteId=1