Longest Arithmetic Progression path in given Binary Tree

Last Updated : 8 Jan, 2026

Given a binary tree, the task is to find the length of the longest path which forms an Arithmetic progression. The path can start and end at any node of the tree.

Examples:

Input: 

Output: 5
Explanation: The longest path forming an AP is: 3->6->9->12->15

Input:

Output: 6
Explanation: The longest path forming an AP is: 2->4->6->8->10->12

Approach: The catch here is that a tree node can only support two AP's, one with the left child and the other one with the right child. Now, to solve this problem, follow the below steps:

  1. Create a variable ans to store the length of the longest path.
  2. Start a depth-first search from the root node, and for each node, find the maximum length path of AP's till left child and right child.
  3. Now find the difference between the current node and its left child, say leftDiff and the difference between the current node and its right child, say rightDiff.
  4. Now find the longest path with difference leftDiff in the left child, say maxLen1 and longest path with difference rightDiff in the right child, say maxLen2.
  5. If leftDiff = (-1)*rightDiff, then both the branches of the current node form an AP, so change ans to the maximum out of the previous value of ans and maxLen1+maxLen2+1.
  6. Else,  change ans to the maximum out of the previous value of ans, (maxLen1+1) and (maxLen2+1), because only one of the two paths can be selected.
  7. Now return maxLen1 and maxLen2 along with the difference of the AP from the current node to the parent node.
  8. Print ans after the function stops.

Below is the implementation of the above approach:

C++
#include <bits/stdc++.h>
using namespace std;

// Tree Node definition
class Node {
public:
    int data;
    Node *left, *right;

    Node(int d) {
        data = d;
        left = right = NULL;
    }
};

// Stores the maximum AP path length found
int ans = 1;

// Returns AP information for the current node
// Each pair represents: {difference, length}
vector<pair<int, int>> maxApPath(Node* root)
{
    // AP info from left and right subtrees
    vector<pair<int, int>> l = { {INT_MAX, 0}, {INT_MAX, 0} };
    vector<pair<int, int>> r = { {INT_MAX, 0}, {INT_MAX, 0} };

    int maxLen1 = 0, maxLen2 = 0;
    int leftDiff = INT_MAX, rightDiff = INT_MAX;

    // Process left child
    if (root->left) {
        // Initialize to count an AP formed by the current node and its left child
        maxLen1 = 1;

        l = maxApPath(root->left);
        leftDiff = root->data - root->left->data;
    }

    // Process right child
    if (root->right) {
        // Initialize to count an AP formed by the current node and its right child
        maxLen2 = 1;

        r = maxApPath(root->right);
        rightDiff = root->data - root->right->data;
    }

    // Extend AP from left subtree
    if (leftDiff == l[0].first || l[0].first == INT_MAX)
        maxLen1 = l[0].second;
    if (leftDiff == l[1].first || l[1].first == INT_MAX)
        maxLen1 = max(maxLen1, l[1].second);

    // Extend AP from right subtree
    if (rightDiff == r[0].first || r[0].first == INT_MAX)
        maxLen2 = r[0].second;
    if (rightDiff == r[1].first || r[1].first == INT_MAX)
        maxLen2 = max(maxLen2, r[1].second);

    // Combine left and right AP paths if possible
    if (leftDiff == -rightDiff)
        ans = max(ans, maxLen1 + maxLen2 + 1);
    else
        ans = max({ans, maxLen1 + 1, maxLen2 + 1});

    // Return AP paths ending at this node
    return {
        { leftDiff,  maxLen1 + 1 },
        { rightDiff, maxLen2 + 1 }
    };
}

int main()
{
    // Constructing the given tree
    Node* root = new Node(1);
    root->left = new Node(8);
    root->right = new Node(6);

    root->left->left = new Node(6);
    root->left->right = new Node(10);

    root->right->left = new Node(3);
    root->right->right = new Node(9);

    root->left->left->right = new Node(4);
    root->left->right->right = new Node(12);

    root->right->right->right = new Node(12);
    root->left->left->right->right = new Node(2);

    root->right->right->right->left = new Node(15);
    root->right->right->right->right = new Node(11);

    // Compute longest AP path
    maxApPath(root);

    cout << ans;
    return 0;
}
Java
import java.util.ArrayList;
import java.util.List;

class GFG {

    // Tree Node definition
    static class Node {
        int data;
        Node left, right;

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

    // Stores the maximum AP path length found
    static int ans = 1;

    // Returns AP information for the current node
    // Each pair represents: {difference, length}
    static List<int[]> maxApPath(Node root) {

        // AP info from left and right subtrees
        List<int[]> l = new ArrayList<>();
        List<int[]> r = new ArrayList<>();

        l.add(new int[]{Integer.MAX_VALUE, 0});
        l.add(new int[]{Integer.MAX_VALUE, 0});
        r.add(new int[]{Integer.MAX_VALUE, 0});
        r.add(new int[]{Integer.MAX_VALUE, 0});

        int maxLen1 = 0, maxLen2 = 0;
        int leftDiff = Integer.MAX_VALUE, rightDiff = Integer.MAX_VALUE;

        // Process left child
        if (root.left != null) {
            // Initialize to count an AP formed by the current node and its left child
            maxLen1 = 1;

            l = maxApPath(root.left);
            leftDiff = root.data - root.left.data;
        }

        // Process right child
        if (root.right != null) {
            // Initialize to count an AP formed by the current node and its right child
            maxLen2 = 1;

            r = maxApPath(root.right);
            rightDiff = root.data - root.right.data;
        }

        // Extend AP from left subtree
        if (leftDiff == l.get(0)[0] || l.get(0)[0] == Integer.MAX_VALUE)
            maxLen1 = l.get(0)[1];
        if (leftDiff == l.get(1)[0] || l.get(1)[0] == Integer.MAX_VALUE)
            maxLen1 = Math.max(maxLen1, l.get(1)[1]);

        // Extend AP from right subtree
        if (rightDiff == r.get(0)[0] || r.get(0)[0] == Integer.MAX_VALUE)
            maxLen2 = r.get(0)[1];
        if (rightDiff == r.get(1)[0] || r.get(1)[0] == Integer.MAX_VALUE)
            maxLen2 = Math.max(maxLen2, r.get(1)[1]);

        // Combine left and right AP paths if possible
        if (leftDiff == -rightDiff)
            ans = Math.max(ans, maxLen1 + maxLen2 + 1);
        else
            ans = Math.max(ans, Math.max(maxLen1 + 1, maxLen2 + 1));

        // Return AP paths ending at this node
        List<int[]> res = new ArrayList<>();
        res.add(new int[]{leftDiff, maxLen1 + 1});
        res.add(new int[]{rightDiff, maxLen2 + 1});

        return res;
    }

    public static void main(String[] args) {

        // Constructing the given tree
        Node root = new Node(1);
        root.left = new Node(8);
        root.right = new Node(6);

        root.left.left = new Node(6);
        root.left.right = new Node(10);

        root.right.left = new Node(3);
        root.right.right = new Node(9);

        root.left.left.right = new Node(4);
        root.left.right.right = new Node(12);

        root.right.right.right = new Node(12);
        root.left.left.right.right = new Node(2);

        root.right.right.right.left = new Node(15);
        root.right.right.right.right = new Node(11);

        // Compute longest AP path
        maxApPath(root);

        System.out.println(ans);
    }
}
Python
class Node:
    # Tree Node definition
    def __init__(self, d):
        self.data = d
        self.left = None
        self.right = None

# Stores the maximum AP path length found
ans = 1

# Returns AP information for the current node
# Each pair represents: {difference, length}
def maxApPath(root):
    global ans

    # AP info from left and right subtrees
    l = [(10**18, 0), (10**18, 0)]
    r = [(10**18, 0), (10**18, 0)]

    maxLen1 = 0
    maxLen2 = 0
    leftDiff = 10**18
    rightDiff = 10**18

    # Process left child
    if root.left:
        # Initialize to count an AP formed by the current node and its left child
        maxLen1 = 1

        l = maxApPath(root.left)
        leftDiff = root.data - root.left.data

    # Process right child
    if root.right:
        # Initialize to count an AP formed by the current node and its right child
        maxLen2 = 1

        r = maxApPath(root.right)
        rightDiff = root.data - root.right.data

    # Extend AP from left subtree
    if leftDiff == l[0][0] or l[0][0] == 10**18:
        maxLen1 = l[0][1]
    if leftDiff == l[1][0] or l[1][0] == 10**18:
        maxLen1 = max(maxLen1, l[1][1])

    # Extend AP from right subtree
    if rightDiff == r[0][0] or r[0][0] == 10**18:
        maxLen2 = r[0][1]
    if rightDiff == r[1][0] or r[1][0] == 10**18:
        maxLen2 = max(maxLen2, r[1][1])

    # Combine left and right AP paths if possible
    if leftDiff == -rightDiff:
        ans = max(ans, maxLen1 + maxLen2 + 1)
    else:
        ans = max(ans, maxLen1 + 1, maxLen2 + 1)

    # Return AP paths ending at this node
    return [(leftDiff, maxLen1 + 1), (rightDiff, maxLen2 + 1)]


if __name__ == "__main__":

    # Constructing the given tree
    root = Node(1)
    root.left = Node(8)
    root.right = Node(6)

    root.left.left = Node(6)
    root.left.right = Node(10)

    root.right.left = Node(3)
    root.right.right = Node(9)

    root.left.left.right = Node(4)
    root.left.right.right = Node(12)

    root.right.right.right = Node(12)
    root.left.left.right.right = Node(2)

    root.right.right.right.left = Node(15)
    root.right.right.right.right = Node(11)

    # Compute longest AP path
    maxApPath(root)

    print(ans)
C#
using System;
using System.Collections.Generic;

class GFG {

    // Tree Node definition
    class Node {
        public int data;
        public Node left, right;

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

    // Stores the maximum AP path length found
    static int ans = 1;

    // Returns AP information for the current node
    // Each pair represents: {difference, length}
    static List<(int, int)> maxApPath(Node root) {

        // AP info from left and right subtrees
        var l = new List<(int, int)> { (int.MaxValue, 0), (int.MaxValue, 0) };
        var r = new List<(int, int)> { (int.MaxValue, 0), (int.MaxValue, 0) };

        int maxLen1 = 0, maxLen2 = 0;
        int leftDiff = int.MaxValue, rightDiff = int.MaxValue;

        // Process left child
        if (root.left != null) {
            // Initialize to count an AP formed by the current node and its left child
            maxLen1 = 1;

            l = maxApPath(root.left);
            leftDiff = root.data - root.left.data;
        }

        // Process right child
        if (root.right != null) {
            // Initialize to count an AP formed by the current node and its right child
            maxLen2 = 1;

            r = maxApPath(root.right);
            rightDiff = root.data - root.right.data;
        }

        // Extend AP from left subtree
        if (leftDiff == l[0].Item1 || l[0].Item1 == int.MaxValue)
            maxLen1 = l[0].Item2;
        if (leftDiff == l[1].Item1 || l[1].Item1 == int.MaxValue)
            maxLen1 = Math.Max(maxLen1, l[1].Item2);

        // Extend AP from right subtree
        if (rightDiff == r[0].Item1 || r[0].Item1 == int.MaxValue)
            maxLen2 = r[0].Item2;
        if (rightDiff == r[1].Item1 || r[1].Item1 == int.MaxValue)
            maxLen2 = Math.Max(maxLen2, r[1].Item2);

        // Combine left and right AP paths if possible
        if (leftDiff == -rightDiff)
            ans = Math.Max(ans, maxLen1 + maxLen2 + 1);
        else
            ans = Math.Max(ans, Math.Max(maxLen1 + 1, maxLen2 + 1));

        // Return AP paths ending at this node
        return new List<(int, int)> {
            (leftDiff, maxLen1 + 1),
            (rightDiff, maxLen2 + 1)
        };
    }

    static void Main() {

        // Constructing the given tree
        Node root = new Node(1);
        root.left = new Node(8);
        root.right = new Node(6);

        root.left.left = new Node(6);
        root.left.right = new Node(10);

        root.right.left = new Node(3);
        root.right.right = new Node(9);

        root.left.left.right = new Node(4);
        root.left.right.right = new Node(12);

        root.right.right.right = new Node(12);
        root.left.left.right.right = new Node(2);

        root.right.right.right.left = new Node(15);
        root.right.right.right.right = new Node(11);

        // Compute longest AP path
        maxApPath(root);

        Console.WriteLine(ans);
    }
}
JavaScript
class Node {
    constructor(d) {
        // Tree Node definition
        this.data = d;
        this.left = null;
        this.right = null;
    }
}

// Stores the maximum AP path length found
let ans = 1;

// Returns AP information for the current node
// Each pair represents: {difference, length}
function maxApPath(root) {

    // AP info from left and right subtrees
    let l = [[Number.MAX_SAFE_INTEGER, 0], [Number.MAX_SAFE_INTEGER, 0]];
    let r = [[Number.MAX_SAFE_INTEGER, 0], [Number.MAX_SAFE_INTEGER, 0]];

    let maxLen1 = 0, maxLen2 = 0;
    let leftDiff = Number.MAX_SAFE_INTEGER;
    let rightDiff = Number.MAX_SAFE_INTEGER;

    // Process left child
    if (root.left) {
        // Initialize to count an AP formed by the current node and its left child
        maxLen1 = 1;

        l = maxApPath(root.left);
        leftDiff = root.data - root.left.data;
    }

    // Process right child
    if (root.right) {
        // Initialize to count an AP formed by the current node and its right child
        maxLen2 = 1;

        r = maxApPath(root.right);
        rightDiff = root.data - root.right.data;
    }

    // Extend AP from left subtree
    if (leftDiff === l[0][0] || l[0][0] === Number.MAX_SAFE_INTEGER)
        maxLen1 = l[0][1];
    if (leftDiff === l[1][0] || l[1][0] === Number.MAX_SAFE_INTEGER)
        maxLen1 = Math.max(maxLen1, l[1][1]);

    // Extend AP from right subtree
    if (rightDiff === r[0][0] || r[0][0] === Number.MAX_SAFE_INTEGER)
        maxLen2 = r[0][1];
    if (rightDiff === r[1][0] || r[1][0] === Number.MAX_SAFE_INTEGER)
        maxLen2 = Math.max(maxLen2, r[1][1]);

    // Combine left and right AP paths if possible
    if (leftDiff === -rightDiff)
        ans = Math.max(ans, maxLen1 + maxLen2 + 1);
    else
        ans = Math.max(ans, maxLen1 + 1, maxLen2 + 1);

    // Return AP paths ending at this node
    return [
        [leftDiff, maxLen1 + 1],
        [rightDiff, maxLen2 + 1]
    ];
}

// Constructing the given tree
let root = new Node(1);
root.left = new Node(8);
root.right = new Node(6);

root.left.left = new Node(6);
root.left.right = new Node(10);

root.right.left = new Node(3);
root.right.right = new Node(9);

root.left.left.right = new Node(4);
root.left.right.right = new Node(12);

root.right.right.right = new Node(12);
root.left.left.right.right = new Node(2);

root.right.right.right.left = new Node(15);
root.right.right.right.right = new Node(11);

// Compute longest AP path
maxApPath(root);

console.log(ans);

 
 


Output
6

Time Complexity: O(N) where N is number of nodes in the Tree 
Auxiliary Space: O(N)


 

Comment