Open In App

Longest Arithmetic Progression path in given Binary Tree

Improve
Improve
Like Article
Like
Save
Share
Report

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++




// C++ code for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Tree Node
class Node {
public:
    int data;
    Node *left, *right;
    Node(int d)
    {
        data = d;
        left = right = NULL;
    }
};
 
// Variable to store the maximum path length
int ans = 1;
 
// Function to find the maximum length
// of a path which forms an AP
vector<pair<int, int> > maxApPath(Node* root)
{
    vector<pair<int, int> > l
        = { { INT_MAX, 0 }, { INT_MAX, 0 } },
        r = { { INT_MAX, 0 }, { INT_MAX, 0 } };
 
    // Variables to store the difference with
    // left and right nodes
    int leftDiff = INT_MAX;
    int rightDiff = INT_MAX;
 
    // If left child exists
    if (root->left) {
        l = maxApPath(root->left);
        leftDiff = (root->data)
                   - (root->left->data);
    }
 
    // If right child exists
    if (root->right) {
        r = maxApPath(root->right);
        rightDiff = (root->data)
                    - (root->right->data);
    }
 
    // Variable to store the maximum length
    // path in the left subtree in which
    // the difference between each
    // node is leftDiff
    int maxLen1 = 0;
 
    // Variable to store the maximum length
    // path in the right subtree in which
    // the difference between each
    // node is rightDiff
    int maxLen2 = 0;
 
    // If a path having the difference
    // leftDiff is found in left subtree
    if (leftDiff == l[0].first
        or l[0].first == INT_MAX) {
        maxLen1 = l[0].second;
    }
    if (leftDiff == l[1].first
        or l[1].first == INT_MAX) {
        maxLen1 = max(maxLen1, l[1].second);
    }
 
    // If a path having the difference
    // rightDiff is found in right subtree
    if (rightDiff == r[0].first
        or r[0].first == INT_MAX) {
        maxLen2 = r[0].second;
    }
    if (rightDiff == r[1].first
        or r[1].first == INT_MAX) {
        maxLen2 = max(maxLen2, r[1].second);
    }
 
    // If both left and right subtree form AP
    if (leftDiff == (-1 * rightDiff)) {
        ans = max(ans, maxLen1 + maxLen2 + 1);
    }
 
    // Else
    else {
        ans = max({ ans, maxLen1 + 1,
                    maxLen2 + 1 });
    }
 
    // Return maximum path for
    // leftDiff and rightDiff
    return { { leftDiff, maxLen1 + 1 },
             { rightDiff, maxLen2 + 1 } };
}
 
// Driver Code
int main()
{
 
    // 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);
 
    maxApPath(root);
    cout << ans;
    return 0;
}


Java




// Java code for the above approach
class GFG{
 
// Tree Node
static class Node {
 
    int data;
    Node left, right;
    Node(int d)
    {
        data = d;
        left = right = null;
    }
};
static class pair
{
    int first, second;
    public pair(int first, int second) 
    {
        this.first = first;
        this.second = second;
    }   
}
   
// Variable to store the maximum path length
static int ans = 1;
 
// Function to find the maximum length
// of a path which forms an AP
static pair[] maxApPath(Node root)
{
    pair [] l
        = { new pair(Integer.MAX_VALUE, 0 ), new pair( Integer.MAX_VALUE, 0 ) };
                pair [] r = { new pair( Integer.MAX_VALUE, 0 ), new pair( Integer.MAX_VALUE, 0 ) };
 
    // Variables to store the difference with
    // left and right nodes
    int leftDiff = Integer.MAX_VALUE;
    int rightDiff = Integer.MAX_VALUE;
 
    // If left child exists
    if (root.left!=null) {
        l = maxApPath(root.left);
        leftDiff = (root.data)
                   - (root.left.data);
    }
 
    // If right child exists
    if (root.right!=null) {
        r = maxApPath(root.right);
        rightDiff = (root.data)
                    - (root.right.data);
    }
 
    // Variable to store the maximum length
    // path in the left subtree in which
    // the difference between each
    // node is leftDiff
    int maxLen1 = 0;
 
    // Variable to store the maximum length
    // path in the right subtree in which
    // the difference between each
    // node is rightDiff
    int maxLen2 = 0;
 
    // If a path having the difference
    // leftDiff is found in left subtree
    if (leftDiff == l[0].first
        || l[0].first == Integer.MAX_VALUE) {
        maxLen1 = l[0].second;
    }
    if (leftDiff == l[1].first
        || l[1].first == Integer.MAX_VALUE) {
        maxLen1 = Math.max(maxLen1, l[1].second);
    }
 
    // If a path having the difference
    // rightDiff is found in right subtree
    if (rightDiff == r[0].first
        || r[0].first == Integer.MAX_VALUE) {
        maxLen2 = r[0].second;
    }
    if (rightDiff == r[1].first
        || r[1].first == Integer.MAX_VALUE) {
        maxLen2 = Math.max(maxLen2, r[1].second);
    }
 
    // If both left and right subtree form AP
    if (leftDiff == (-1 * rightDiff)) {
        ans = Math.max(ans, maxLen1 + maxLen2 + 1);
    }
 
    // Else
    else {
        ans = Math.max( Math.max(ans, maxLen1 + 1),
                 maxLen2 + 1 );
    }
 
    // Return maximum path for
    // leftDiff and rightDiff
    return new pair[] { new pair(leftDiff, maxLen1 + 1 ),
            new pair( rightDiff, maxLen2 + 1 ) };
}
 
// Driver Code
public static void main(String[] args)
{
 
    // 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);
 
    maxApPath(root);
    System.out.print(ans);
}
}
 
// This code is contributed by shikhasingrajput


Python3




# Python code for the above approach
 
# Tree Node
class Node:
 
    def __init__(self, d):
        self.data = d
        self.left = self.right = None
 
# Variable to store the maximum path length
ans = 1;
 
# Function to find the maximum length
# of a path which forms an AP
def maxApPath(root):
    l = [{ "first": 10 ** 9, "second": 0 }, { "first": 10 ** 9, "second": 0 }]
    r = [{ "first": 10 ** 9, "second": 0 }, { "first": 10 ** 9, "second": 0 }];
 
    # Variables to store the difference with
    # left and right nodes
    leftDiff = 10 ** 9;
    rightDiff = 10 ** 9;
 
    # If left child exists
    if (root.left):
        l = maxApPath(root.left);
        leftDiff = (root.data) - (root.left.data);
     
    # If right child exists
    if (root.right) :
        r = maxApPath(root.right);
        rightDiff = (root.data) - (root.right.data);
     
    # Variable to store the maximum length
    # path in the left subtree in which
    # the difference between each
    # node is leftDiff
    maxLen1 = 0;
 
    # Variable to store the maximum length
    # path in the right subtree in which
    # the difference between each
    # node is rightDiff
    maxLen2 = 0;
 
    # If a path having the difference
    # leftDiff is found in left subtree
    if (leftDiff == l[0]["first"] or l[0]["first"] == 10 ** 9):
        maxLen1 = l[0]["second"];
     
    if (leftDiff == l[1]["first"] or l[1]["first"] == 10 ** 9):
        maxLen1 = max(maxLen1, l[1]["second"]);
     
 
    # If a path having the difference
    # rightDiff is found in right subtree
    if (rightDiff == r[0]["first"] or r[0]["first"] == 10 ** 9):
        maxLen2 = r[0]["second"];
     
    if (rightDiff == r[1]["first"] or r[1]["first"] == 10 ** 9):
        maxLen2 = max(maxLen2, r[1]["second"]);
     
    global ans;
 
    # If both left and right subtree form AP
    if (leftDiff == (-1 * rightDiff)):
        ans = max(ans, maxLen1 + maxLen2 + 1);
     
 
    # Else
    else:
        ans = max(ans, max(maxLen1 + 1, maxLen2 + 1));
     
 
    # Return maximum path for
    # leftDiff and rightDiff
    return [{ "first": leftDiff, "second": maxLen1 + 1 },
    { "first": rightDiff, "second": maxLen2 + 1 }];
 
 
# Driver Code
# 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);
 
maxApPath(root);
print(ans);
 
# This code is contributed by gfgking


C#




// C# code for the above approach
using System;
using System.Collections.Generic;
public class GFG {
 
  // Tree Node
  public class Node {
 
    public int data;
    public Node left, right;
 
    public Node(int d) {
      data = d;
      left = right = null;
    }
  };
 
  public class pair {
    public int first, second;
 
    public pair(int first, int second) {
      this.first = first;
      this.second = second;
    }
  }
 
  // Variable to store the maximum path length
  static int ans = 1;
 
  // Function to find the maximum length
  // of a path which forms an AP
  static pair[] maxApPath(Node root) {
    pair[] l = { new pair(int.MaxValue, 0), new pair(int.MaxValue, 0) };
    pair[] r = { new pair(int.MaxValue, 0), new pair(int.MaxValue, 0) };
 
    // Variables to store the difference with
    // left and right nodes
    int leftDiff = int.MaxValue;
    int rightDiff = int.MaxValue;
 
    // If left child exists
    if (root.left != null) {
      l = maxApPath(root.left);
      leftDiff = (root.data) - (root.left.data);
    }
 
    // If right child exists
    if (root.right != null) {
      r = maxApPath(root.right);
      rightDiff = (root.data) - (root.right.data);
    }
 
    // Variable to store the maximum length
    // path in the left subtree in which
    // the difference between each
    // node is leftDiff
    int maxLen1 = 0;
 
    // Variable to store the maximum length
    // path in the right subtree in which
    // the difference between each
    // node is rightDiff
    int maxLen2 = 0;
 
    // If a path having the difference
    // leftDiff is found in left subtree
    if (leftDiff == l[0].first || l[0].first == int.MaxValue) {
      maxLen1 = l[0].second;
    }
    if (leftDiff == l[1].first || l[1].first == int.MaxValue) {
      maxLen1 = Math.Max(maxLen1, l[1].second);
    }
 
    // If a path having the difference
    // rightDiff is found in right subtree
    if (rightDiff == r[0].first || r[0].first == int.MaxValue) {
      maxLen2 = r[0].second;
    }
    if (rightDiff == r[1].first || r[1].first == int.MaxValue) {
      maxLen2 = Math.Max(maxLen2, r[1].second);
    }
 
    // If both left and right subtree form AP
    if (leftDiff == (-1 * rightDiff)) {
      ans = Math.Max(ans, maxLen1 + maxLen2 + 1);
    }
 
    // Else
    else {
      ans = Math.Max(Math.Max(ans, maxLen1 + 1), maxLen2 + 1);
    }
 
    // Return maximum path for
    // leftDiff and rightDiff
    return new pair[] { new pair(leftDiff, maxLen1 + 1), new pair(rightDiff, maxLen2 + 1) };
  }
 
  // Driver Code
  public static void Main(String[] args) {
 
    // 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);
 
    maxApPath(root);
    Console.Write(ans);
  }
}
 
// This code is contributed by Rajput-Ji


Javascript




<script>
      // JavaScript code for the above approach
 
      // Tree Node
      class Node {
 
          constructor(d) {
              this.data = d;
              this.left = this.right = null;
          }
      };
 
      // Variable to store the maximum path length
      let ans = 1;
 
      // Function to find the maximum length
      // of a path which forms an AP
      function maxApPath(root) {
          let l
              = [{ first: Number.MAX_VALUE, second: 0 }, { first: Number.MAX_VALUE, second: 0 }],
              r = [{ first: Number.MAX_VALUE, second: 0 }, { first: Number.MAX_VALUE, second: 0 }];
 
          // Variables to store the difference with
          // left and right nodes
          let leftDiff = Number.MAX_VALUE;
          let rightDiff = Number.MAX_VALUE;
 
          // If left child exists
          if (root.left) {
              l = maxApPath(root.left);
              leftDiff = (root.data)
                  - (root.left.data);
          }
 
          // If right child exists
          if (root.right) {
              r = maxApPath(root.right);
              rightDiff = (root.data)
                  - (root.right.data);
          }
 
          // Variable to store the maximum length
          // path in the left subtree in which
          // the difference between each
          // node is leftDiff
          let maxLen1 = 0;
 
          // Variable to store the maximum length
          // path in the right subtree in which
          // the difference between each
          // node is rightDiff
          let maxLen2 = 0;
 
          // If a path having the difference
          // leftDiff is found in left subtree
          if (leftDiff == l[0].first
              || l[0].first == Number.MAX_VALUE) {
              maxLen1 = l[0].second;
          }
          if (leftDiff == l[1].first
              || l[1].first == Number.MAX_VALUE) {
              maxLen1 = Math.max(maxLen1, l[1].second);
          }
 
          // If a path having the difference
          // rightDiff is found in right subtree
          if (rightDiff == r[0].first
              || r[0].first == Number.MAX_VALUE) {
              maxLen2 = r[0].second;
          }
          if (rightDiff == r[1].first
              || r[1].first == Number.MAX_VALUE) {
              maxLen2 = Math.max(maxLen2, r[1].second);
          }
 
          // If both left and right subtree form AP
          if (leftDiff == (-1 * rightDiff)) {
              ans = Math.max(ans, maxLen1 + maxLen2 + 1);
          }
 
          // Else
          else {
              ans = Math.max(ans, Math.max(maxLen1 + 1,
                  maxLen2 + 1));
          }
 
          // Return maximum path for
          // leftDiff and rightDiff
          return [{ first: leftDiff, second: maxLen1 + 1 },
          { first: rightDiff, second: maxLen2 + 1 }];
      }
 
      // Driver Code
 
 
      // 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);
 
      maxApPath(root);
      document.write(ans);
 
     // This code is contributed by Potta Lokesh
  </script>


 
 

Output: 

6

 

 

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

 



Last Updated : 28 Feb, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads