Node and Ancestor Max Diff

Last Updated : 1 Aug, 2026

Given a root  binary tree, you need to find the maximum value which you can get by subtracting the value of node B from the value of node A, where A and B are two nodes of the binary tree and A is an ancestor of B. 

Examples:

Input: root = [5, 2, 1]

blobid0_1749728452

Output: 4
Explanation: The maximum difference we can get is 4, which is between 5 and 1.

Input: root = [1, 2, 3, N, N, N, 7]

blobid1_1749728553

Output: -1
Explanation: The maximum difference we can get is -1, which is between 1 and 2.

Try It Yourself
redirect icon

[Naive Approach] DFS for Every Ancestor - O(n^2) Time and O(h) Space

The idea is to consider every node as an ancestor and traverse all nodes in its subtree. For every ancestor-descendant pair, compute their difference and update the maximum answer.

Working of Approach:

  • Traverse every node and treat it as the ancestor.
  • Perform DFS on its left and right subtrees.
  • For every descendant, calculate ancestor->data - descendant->data.
  • Keep updating the maximum difference.
  • Return the maximum value obtained.
C++
#include <climits>
#include <iostream>
#include <queue>
#include <sstream>
#include <vector>
using namespace std;

class Node
{
  public:
    int data;
    Node *left;
    Node *right;

    Node(int val)
    {
        data = val;
        left = right = nullptr;
    }
};

// DFS to check all descendants of an ancestor
void findDiff(Node *ancestor, Node *curr, int &ans)
{

    if (curr == nullptr)
        return;

    // Update maximum difference
    ans = max(ans, ancestor->data - curr->data);

    findDiff(ancestor, curr->left, ans);
    findDiff(ancestor, curr->right, ans);
}

// Treat every node as ancestor
void traverse(Node *root, int &ans)
{

    if (root == nullptr)
        return;

    findDiff(root, root->left, ans);
    findDiff(root, root->right, ans);

    traverse(root->left, ans);
    traverse(root->right, ans);
}

int maxDiff(Node *root)
{

    int ans = INT_MIN;

    traverse(root, ans);

    return ans;
}

// Function to build tree from level order input
Node *buildTree(string str)
{

    if (str.size() == 0 || str[0] == 'N')
        return nullptr;

    vector<string> ip;
    stringstream ss(str);
    string temp;

    while (ss >> temp)
        ip.push_back(temp);

    Node *root = new Node(stoi(ip[0]));

    queue<Node *> q;
    q.push(root);

    int i = 1;

    while (!q.empty() && i < ip.size())
    {

        Node *curr = q.front();
        q.pop();

        if (ip[i] != "N")
        {
            curr->left = new Node(stoi(ip[i]));
            q.push(curr->left);
        }
        i++;

        if (i >= ip.size())
            break;

        if (ip[i] != "N")
        {
            curr->right = new Node(stoi(ip[i]));
            q.push(curr->right);
        }
        i++;
    }

    return root;
}

int main()
{

    // Construct the following binary tree
    //        5
    //       / \
    //      2   1

    Node *root = new Node(5);
    root->left = new Node(2);
    root->right = new Node(1);

    cout << maxDiff(root);

    return 0;
}
Java
import java.util.*;

// Structure of a Binary Tree Node
class Node {
    int data;
    Node left, right;

    Node(int val)
    {
        data = val;
        left = right = null;
    }
}

public class GFG {

    // DFS to check all descendants of an ancestor
    static void findDiff(Node ancestor, Node curr,
                         int[] ans)
    {

        if (curr == null)
            return;

        // Update maximum difference
        ans[0]
            = Math.max(ans[0], ancestor.data - curr.data);

        findDiff(ancestor, curr.left, ans);
        findDiff(ancestor, curr.right, ans);
    }

    // Treat every node as ancestor
    static void traverse(Node root, int[] ans)
    {

        if (root == null)
            return;

        findDiff(root, root.left, ans);
        findDiff(root, root.right, ans);

        traverse(root.left, ans);
        traverse(root.right, ans);
    }

    static int maxDiff(Node root)
    {

        int[] ans = { Integer.MIN_VALUE };

        traverse(root, ans);

        return ans[0];
    }

    // Construct binary tree from level order input
    static Node buildTree(String str)
    {

        if (str.length() == 0 || str.charAt(0) == 'N')
            return null;

        String[] ip = str.split("\\s+");

        Node root = new Node(Integer.parseInt(ip[0]));

        Queue<Node> q = new LinkedList<>();
        q.offer(root);

        int i = 1;

        while (!q.isEmpty() && i < ip.length) {

            Node curr = q.poll();

            if (!ip[i].equals("N")) {
                curr.left
                    = new Node(Integer.parseInt(ip[i]));
                q.offer(curr.left);
            }
            i++;

            if (i >= ip.length)
                break;

            if (!ip[i].equals("N")) {
                curr.right
                    = new Node(Integer.parseInt(ip[i]));
                q.offer(curr.right);
            }
            i++;
        }

        return root;
    }

    public static void main(String[] args)
    {

        // Construct the following binary tree
        //        5
        //       / \
        //      2   1

        Node root = new Node(5);
        root.left = new Node(2);
        root.right = new Node(1);

        System.out.println(maxDiff(root));
    }
}
Python
class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None

# DFS to check all descendants of an ancestor


def findDiff(ancestor, curr, ans):
    if curr is None:
        return
    # Update maximum difference
    ans[0] = max(ans[0], ancestor.data - curr.data)
    findDiff(ancestor, curr.left, ans)
    findDiff(ancestor, curr.right, ans)


# Treat every node as ancestor


def traverse(root, ans):
    if root is None:
        return
    findDiff(root, root.left, ans)
    findDiff(root, root.right, ans)
    traverse(root.left, ans)
    traverse(root.right, ans)


def maxDiff(root):
    ans = [float('-inf')]
    traverse(root, ans)
    return ans[0]


# Function to build tree from level order input


def buildTree(s):
    if not s or s[0] == 'N':
        return None
    ip = s.split()
    root = Node(int(ip[0]))
    queue = [root]
    i = 1
    while queue and i < len(ip):
        curr = queue.pop(0)
        if ip[i] != 'N':
            curr.left = Node(int(ip[i]))
            queue.append(curr.left)
        i += 1
        if i >= len(ip):
            break
        if ip[i] != 'N':
            curr.right = Node(int(ip[i]))
            queue.append(curr.right)
        i += 1
    return root


# Driver Code
if __name__ == '__main__':
    root = buildTree('5 2 1')
    print(maxDiff(root))
C#
using System;
using System.Collections.Generic;

// Structure of a Binary Tree Node
class Node {
    public int data;
    public Node left, right;

    public Node(int val)
    {
        data = val;
        left = right = null;
    }
}

class GFG {
    // DFS to check all descendants of an ancestor
    static void FindDiff(Node ancestor, Node curr,
                         ref int ans)
    {
        if (curr == null)
            return;

        // Update maximum difference
        ans = Math.Max(ans, ancestor.data - curr.data);

        FindDiff(ancestor, curr.left, ref ans);
        FindDiff(ancestor, curr.right, ref ans);
    }

    // Treat every node as ancestor
    static void Traverse(Node root, ref int ans)
    {
        if (root == null)
            return;

        FindDiff(root, root.left, ref ans);
        FindDiff(root, root.right, ref ans);

        Traverse(root.left, ref ans);
        Traverse(root.right, ref ans);
    }

    static int maxDiff(Node root)
    {
        int ans = int.MinValue;

        Traverse(root, ref ans);

        return ans;
    }

    // Construct binary tree from level order input
    static Node BuildTree(string str)
    {
        if (string.IsNullOrEmpty(str) || str[0] == 'N')
            return null;

        string[] ip = str.Split();

        Node root = new Node(int.Parse(ip[0]));

        Queue<Node> q = new Queue<Node>();
        q.Enqueue(root);

        int i = 1;

        while (q.Count > 0 && i < ip.Length) {
            Node curr = q.Dequeue();

            if (ip[i] != "N") {
                curr.left = new Node(int.Parse(ip[i]));
                q.Enqueue(curr.left);
            }
            i++;

            if (i >= ip.Length)
                break;

            if (ip[i] != "N") {
                curr.right = new Node(int.Parse(ip[i]));
                q.Enqueue(curr.right);
            }
            i++;
        }

        return root;
    }

    static void Main()
    {
        // Construct the following binary tree
        //        5
        //       / \
        //      2   1

        Node root = new Node(5);
        root.left = new Node(2);
        root.right = new Node(1);

        Console.WriteLine(maxDiff(root));
    }
}
JavaScript
// Node structure
function Node(val)
{
    this.data = val;
    this.left = null;
    this.right = null;
}

// DFS to check all descendants of an ancestor
function findDiff(ancestor, curr, ans)
{

    if (curr === null)
        return;

    // Update maximum difference
    ans.value
        = Math.max(ans.value, ancestor.data - curr.data);

    findDiff(ancestor, curr.left, ans);
    findDiff(ancestor, curr.right, ans);
}

// Treat every node as ancestor
function traverse(root, ans)
{

    if (root === null)
        return;

    findDiff(root, root.left, ans);
    findDiff(root, root.right, ans);

    traverse(root.left, ans);
    traverse(root.right, ans);
}

function maxDiff(root)
{

    let ans = {value : Number.MIN_SAFE_INTEGER};

    traverse(root, ans);

    return ans.value;
}

// Function to build tree from level order input
function buildTree(str)
{

    if (str.length === 0 || str[0] === "N")
        return null;

    let ip = str.trim().split(/\s+/);

    let root = new Node(parseInt(ip[0]));

    let q = [];
    q.push(root);

    let i = 1;

    while (q.length > 0 && i < ip.length) {

        let curr = q.shift();

        if (ip[i] !== "N") {
            curr.left = new Node(parseInt(ip[i]));
            q.push(curr.left);
        }
        i++;

        if (i >= ip.length)
            break;

        if (ip[i] !== "N") {
            curr.right = new Node(parseInt(ip[i]));
            q.push(curr.right);
        }
        i++;
    }

    return root;
}

// Driver Code

// Construct the following binary tree
//        5
//       / \
//      2   1

let root = new Node(5);
root.left = new Node(2);
root.right = new Node(1);

console.log(maxDiff(root));

Output
4

[Expected Approach] Postorder Traversal with Minimum Subtree Value - O(n) Time and O(h) Space

The idea is to traverse the tree in postorder and return the minimum value present in every subtree. This minimum descendant value is used to compute the maximum difference for the current ancestor.

Working of Approach:

  • Traverse the tree using postorder recursion.
  • Return the minimum value from the left and right subtrees.
  • Update the answer using current node - minimum descendant.
  • Return the minimum value in the current subtree.
  • The final answer is the maximum difference found.

Let us understand with an example:
Input: root = [5, 2, 1]

blobid0_1749728452
  • The leaf nodes 2 and 1 return their values as the minimum values of their respective subtrees.
  • For node 5, the minimum value among its descendants is 1.
  • The difference 5 - 1 = 4 is calculated and the answer is updated.
  • The minimum value in the subtree rooted at 5 remains 1.
  • Therefore, the maximum difference between an ancestor and its descendant is 4.
C++
#include <climits>
#include <iostream>
#include <queue>
#include <sstream>
#include <vector>
using namespace std;

class Node
{
  public:
    int data;
    Node *left;
    Node *right;

    Node(int val)
    {
        data = val;
        left = right = nullptr;
    }
};

int maxDiffUtil(Node *t, int *res)
{
    // returning Maximum int value if node is null.
    if (t == nullptr)
        return INT_MAX;

    // if there are no child nodes then we just return data at current node.
    if (t->left == nullptr && t->right == nullptr)
        return t->data;

    // recursively calling for left and right subtrees and
    // choosing their minimum.
    int val = min(maxDiffUtil(t->left, res), maxDiffUtil(t->right, res));

    // updating res if (node value - min value from subtrees) is bigger than res.
    *res = max(*res, t->data - val);

    // returning minimum value got so far.
    return min(val, t->data);
}

// Function to return the maximum difference between any node and its ancestor.
int maxDiff(Node *root)
{
    int res = INT_MIN;
    maxDiffUtil(root, &res);
    // returning the result.
    return res;
}

// Function to build tree from level order input
Node *buildTree(string str)
{

    if (str.size() == 0 || str[0] == 'N')
        return nullptr;

    vector<string> ip;
    stringstream ss(str);
    string temp;

    while (ss >> temp)
        ip.push_back(temp);

    Node *root = new Node(stoi(ip[0]));

    queue<Node *> q;
    q.push(root);

    int i = 1;

    while (!q.empty() && i < ip.size())
    {

        Node *curr = q.front();
        q.pop();

        if (ip[i] != "N")
        {
            curr->left = new Node(stoi(ip[i]));
            q.push(curr->left);
        }
        i++;

        if (i >= ip.size())
            break;

        if (ip[i] != "N")
        {
            curr->right = new Node(stoi(ip[i]));
            q.push(curr->right);
        }
        i++;
    }

    return root;
}

int main()
{

    // Construct the following binary tree
    //        5
    //       / \
    //      2   1

    Node *root = new Node(5);
    root->left = new Node(2);
    root->right = new Node(1);

    cout << maxDiff(root);

    return 0;
}
Java
import java.util.*;

// Structure of a Binary Tree Node
class Node {
    int data;
    Node left, right;

    Node(int val)
    {
        data = val;
        left = right = null;
    }
}

public class GFG {

    static int maxDiffUtil(Node t, int[] res)
    {

        // Returning maximum value if node is null
        if (t == null)
            return Integer.MAX_VALUE;

        // Leaf node
        if (t.left == null && t.right == null)
            return t.data;

        // Recursively find minimum from left and right
        // subtrees
        int val = Math.min(maxDiffUtil(t.left, res),
                           maxDiffUtil(t.right, res));

        // Update answer
        res[0] = Math.max(res[0], t.data - val);

        // Return minimum value so far
        return Math.min(val, t.data);
    }

    // Function to return the maximum difference
    static int maxDiff(Node root)
    {

        int[] res = { Integer.MIN_VALUE };

        maxDiffUtil(root, res);

        return res[0];
    }

    // Function to build tree from level order input
    static Node buildTree(String str)
    {

        if (str.length() == 0 || str.charAt(0) == 'N')
            return null;

        String[] ip = str.split("\\s+");

        Node root = new Node(Integer.parseInt(ip[0]));

        Queue<Node> q = new LinkedList<>();
        q.offer(root);

        int i = 1;

        while (!q.isEmpty() && i < ip.length) {

            Node curr = q.poll();

            if (!ip[i].equals("N")) {
                curr.left
                    = new Node(Integer.parseInt(ip[i]));
                q.offer(curr.left);
            }
            i++;

            if (i >= ip.length)
                break;

            if (!ip[i].equals("N")) {
                curr.right
                    = new Node(Integer.parseInt(ip[i]));
                q.offer(curr.right);
            }
            i++;
        }

        return root;
    }

    public static void main(String[] args)
    {

        // Construct the following binary tree
        //        5
        //       / \
        //      2   1

        Node root = new Node(5);
        root.left = new Node(2);
        root.right = new Node(1);

        System.out.println(maxDiff(root));
    }
}
Python
from queue import Queue

class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None

def maxDiffUtil(t, res):
    # returning Maximum int value if node is null.
    if t is None:
        return float('inf')

    # if there are no child nodes then we just return data at current node.
    if t.left is None and t.right is None:
        return t.data

    # recursively calling for left and right subtrees and
    # choosing their minimum.
    val = min(maxDiffUtil(t.left, res), maxDiffUtil(t.right, res))

    # updating res if (node value - min value from subtrees) is bigger than res.
    res[0] = max(res[0], t.data - val)

    # returning minimum value got so far.
    return min(val, t.data)

# Function to return the maximum difference between any node and its ancestor.
def maxDiff(root):
    res = [float('-inf')]
    maxDiffUtil(root, res)
    # returning the result.
    return res[0]

# Function to build tree from level order input
def buildTree(str):
    if str == "" or str[0] == 'N':
        return None

    ip = str.split()

    root = Node(int(ip[0]))
    q = Queue()
    q.put(root)

    i = 1

    while not q.empty() and i < len(ip):
        curr = q.get()

        if ip[i]!= 'N':
            curr.left = Node(int(ip[i]))
            q.put(curr.left)
        i += 1

        if i >= len(ip):
            break

        if ip[i]!= 'N':
            curr.right = Node(int(ip[i]))
            q.put(curr.right)
        i += 1

    return root


if __name__ == '__main__':

    # Construct the following binary tree
    #        5
    #       / \
    #      2   1

    root = Node(5)
    root.left = Node(2)
    root.right = Node(1)

    print(maxDiff(root))
C#
using System;
using System.Collections.Generic;

// Structure of a Binary Tree Node
class Node {
    public int data;
    public Node left, right;

    public Node(int val)
    {
        data = val;
        left = right = null;
    }
}

class GFG {
    static int MaxDiffUtil(Node t, ref int res)
    {
        // Returning maximum value if node is null
        if (t == null)
            return int.MaxValue;

        // Leaf node
        if (t.left == null && t.right == null)
            return t.data;

        // Recursively find minimum from left and right
        // subtrees
        int val = Math.Min(MaxDiffUtil(t.left, ref res),
                           MaxDiffUtil(t.right, ref res));

        // Update answer
        res = Math.Max(res, t.data - val);

        // Return minimum value so far
        return Math.Min(val, t.data);
    }

    // Function to return the maximum difference
    static int maxDiff(Node root)
    {
        int res = int.MinValue;

        MaxDiffUtil(root, ref res);

        return res;
    }

    // Function to build tree from level order input
    static Node BuildTree(string str)
    {
        if (string.IsNullOrEmpty(str) || str[0] == 'N')
            return null;

        string[] ip = str.Split();

        Node root = new Node(int.Parse(ip[0]));

        Queue<Node> q = new Queue<Node>();
        q.Enqueue(root);

        int i = 1;

        while (q.Count > 0 && i < ip.Length) {
            Node curr = q.Dequeue();

            if (ip[i] != "N") {
                curr.left = new Node(int.Parse(ip[i]));
                q.Enqueue(curr.left);
            }
            i++;

            if (i >= ip.Length)
                break;

            if (ip[i] != "N") {
                curr.right = new Node(int.Parse(ip[i]));
                q.Enqueue(curr.right);
            }
            i++;
        }

        return root;
    }

    static void Main()
    {
        // Construct the following binary tree
        //        5
        //       / \
        //      2   1

        Node root = new Node(5);
        root.left = new Node(2);
        root.right = new Node(1);

        Console.WriteLine(maxDiff(root));
    }
}
JavaScript
// Node structure
function Node(val)
{
    this.data = val;
    this.left = null;
    this.right = null;
}

function maxDiffUtil(t, res)
{

    // Returning maximum value if node is null
    if (t === null)
        return Number.MAX_SAFE_INTEGER;

    // Leaf node
    if (t.left === null && t.right === null)
        return t.data;

    // Recursively find minimum from left and right subtrees
    let val = Math.min(maxDiffUtil(t.left, res),
                       maxDiffUtil(t.right, res));

    // Update answer
    res.value = Math.max(res.value, t.data - val);

    // Return minimum value so far
    return Math.min(val, t.data);
}

// Function to return the maximum difference
function maxDiff(root)
{

    let res = {value : Number.MIN_SAFE_INTEGER};

    maxDiffUtil(root, res);

    return res.value;
}

// Function to build tree from level order input
function buildTree(str)
{

    if (str.length === 0 || str[0] === "N")
        return null;

    let ip = str.trim().split(/\s+/);

    let root = new Node(parseInt(ip[0]));

    let q = [];
    q.push(root);

    let i = 1;

    while (q.length > 0 && i < ip.length) {

        let curr = q.shift();

        if (ip[i] !== "N") {
            curr.left = new Node(parseInt(ip[i]));
            q.push(curr.left);
        }
        i++;

        if (i >= ip.length)
            break;

        if (ip[i] !== "N") {
            curr.right = new Node(parseInt(ip[i]));
            q.push(curr.right);
        }
        i++;
    }

    return root;
}

// Driver Code

// Construct the following binary tree
//        5
//       / \
//      2   1

let root = new Node(5);
root.left = new Node(2);
root.right = new Node(1);

console.log(maxDiff(root));

Output
4
Comment