Open In App

Number of Isosceles triangles in a binary tree

Pre-Requisites: Depth First Search | Parent Array Representation
Given a parent array representation of a binary tree, we need to find the number of Isosceles triangles in the binary tree. 
Consider a parent array representing a binary tree: 
Parent Array: 
 



Given below is the tree representation of the given parent array. 
Binary Tree: 
 



There are three types of isosceles triangles which can be found inside a binary tree. These three different types of isosceles triangles can be handled as three different cases.

Case 1: Apex(Vertex against the base sharing equal sides) has two successors(both direct/indirect). 
This case can be represented as: 
 

In the given tree, there are 6 such isosceles triangles i.e; (0, 1, 2), (0, 3, 6), (1, 3, 4), (1, 7, 9), (4, 8, 9), (2, 5, 6) 

Pseudo Code: 

Case 2: Apex has a left successor(direct/indirect) and apex itself is a right successor(direct/indirect) of its parent. 
This case can be represented as: 
 

In the given tree, there are 2 such isosceles triangles i.e; (1, 8, 4), (0, 5, 2)

Pseudo Code: 

Case 3: Apex has a right successor(direct/indirect) and apex itself is a left successor(direct/indirect) of its parent. 
This case can be represented as: 
 

In the given tree, there is 1 such isosceles triangle i.e; (0, 1, 4)

Pseudo Code: 

Pseudo Code legend: 
left_down[i] -> maximum distance of ith node from its farthest left successor 
right_down[i] -> maximum distance of ith node from its farthest right successor 
left_up[i] -> maximum distance of ith node from its farthest left predecessor 
right_up[i] -> maximum distance of ith node from its farthest right predecessor

Below is the implementation to calculate the number of isosceles triangles present in a given binary tree:  




/* C++ program for calculating number of
isosceles triangles present in a binary tree */
#include <bits/stdc++.h>
using namespace std;
 
#define MAX_SZ int(1e5)
 
/* Data Structure used to store
   Binary Tree in form of Graph */
vector<int>* graph;
 
// Data variables
int right_down[MAX_SZ];
int left_down[MAX_SZ];
int right_up[MAX_SZ];
int left_up[MAX_SZ];
 
/* Utility function used to
   start a DFS traversal over a node */
void DFS(int u, int* parent)
{
 
    if (graph[u].size() != 0)
        sort(graph[u].begin(), graph[u].end());
 
    if (parent[u] != -1) {
        if (graph[parent[u]].size() > 1) {
            /* check if current node is
                                left child of its parent */
            if (u == graph[parent[u]][0]) {
                right_up[u] += right_up[parent[u]] + 1;
            }
            // current node is right child of its parent
            else {
                left_up[u] += left_up[parent[u]] + 1;
            }
        }
        /* check if current node is left and
                            only child of its parent */
        else {
            right_up[u] += right_up[parent[u]] + 1;
        }
    }
    for (int i = 0; i < graph[u].size(); ++i) {
 
        int v = graph[u][i];
 
        // iterating over subtree
        DFS(v, parent);
 
        // left child of current node
        if (i == 0) {
            left_down[u] += left_down[v] + 1;
        }
        // right child of current node
        else {
            right_down[u] += right_down[v] + 1;
        }
    }
}
 
/* utility function used to generate
                graph from parent array */
int generateGraph(int* parent, int n)
{
 
    int root;
 
    graph = new vector<int>[n];
 
    // Generating graph from parent array
    for (int i = 0; i < n; ++i) {
 
        // check for non-root node
        if (parent[i] != -1) {
            /* creating an edge from node with number
             parent[i] to node with number i */
            graph[parent[i]].push_back(i);
        }
        // initializing root
        else {
            root = i;
        }
 
        // Initializing necessary data variables
        left_up[i] = 0;
        right_up[i] = 0;
        left_down[i] = 0;
        right_down[i] = 0;
    }
    // root of the binary tree
    return root;
}
 
// Driver Function
int main()
{
 
    int n = 10;
 
    /* Parent array used for storing
       parent of each node */
    int parent[] = { -1, 0, 0, 1, 1, 2, 2, 3, 4, 4 };
 
    /* generateGraph() function generates a graph a
       returns root of the graph which can be used for
       starting DFS traversal */
    int root = generateGraph(parent, n);
 
    // triggering dfs for traversal over graph
    DFS(root, parent);
 
    int count = 0;
 
    // Calculation of number of isosceles triangles
    for (int i = 0; i < n; ++i) {
        count += min(right_down[i], right_up[i]);
        count += min(left_down[i], left_up[i]);
        count += min(left_down[i], right_down[i]);
    }
 
    cout << "Number of isosceles triangles "
         << "in the given binary tree are " << count;
 
    return 0;
}




/* JAVA program for calculating number of
isosceles triangles present in a binary tree */
 
import java.io.*;
import java.util.*;
 
@SuppressWarnings("unchecked")
class Isosceles_triangles {
 
    static int MAX_SZ = (int)1e5;
 
    /* Data Structure used to store
       Binary Tree in form of Graph */
    static ArrayList<Integer>[] graph;
 
    // Data variables
    static int[] right_down = new int[MAX_SZ];
    static int[] left_down = new int[MAX_SZ];
    static int[] right_up = new int[MAX_SZ];
    static int[] left_up = new int[MAX_SZ];
 
    /* Utility function used to
       start a DFS traversal over a node */
    public static void DFS(int u, int[] parent)
    {
 
        if (graph[u] != null)
            Collections.sort(graph[u]);
 
        if (parent[u] != -1) {
            if (graph[parent[u]].size() > 1) {
                /* check if current node is
                                left child of its parent */
                if (u == graph[parent[u]].get(0)) {
                    right_up[u] += right_up[parent[u]] + 1;
                }
                // current node is right child of its parent
                else {
                    left_up[u] += left_up[parent[u]] + 1;
                }
            }
            /* check if current node is left and
                                only child of its parent */
            else {
                right_up[u] += right_up[parent[u]] + 1;
            }
        }
 
        if (graph[u] == null)
            return;
 
        for (int i = 0; i < graph[u].size(); ++i) {
 
            int v = graph[u].get(i);
 
            // iterating over subtree
            DFS(v, parent);
 
            // left child of current node
            if (i == 0) {
                left_down[u] += left_down[v] + 1;
            }
            // right child of current node
            else {
                right_down[u] += right_down[v] + 1;
            }
        }
    }
 
    static int min(Integer a, Integer b)
    {
        return (a < b) ? a : b;
    }
 
    /* utility function used to generate
                    graph from parent array */
    public static int generateGraph(int[] parent, int n)
    {
 
        int root = -1;
 
        graph = (ArrayList<Integer>[]) new ArrayList[n];
 
        // Generating graph from parent array
        for (int i = 0; i < n; ++i) {
 
            // check for non-root node
            if (parent[i] != -1) {
                /* creating an edge from node with number
                 parent[i] to node with number i */
                if (graph[parent[i]] == null) {
                    graph[parent[i]] = new ArrayList<Integer>();
                }
                graph[parent[i]].add(i);
                // System.out.println(graph);
            }
            // initializing root
            else {
                root = i;
            }
 
            // Initializing necessary data variables
            left_up[i] = 0;
            right_up[i] = 0;
            left_down[i] = 0;
            right_down[i] = 0;
        }
        // root of the binary tree
        return root;
    }
 
    // Driver Function
    public static void main(String[] args)
    {
 
        int n = 10;
 
        /* Parent array used for storing
           parent of each node */
        int[] parent = new int[] { -1, 0, 0, 1, 1, 2, 2, 3, 4, 4 };
 
        /* generateGraph() function generates a graph a
           returns root of the graph which can be used for
           starting DFS traversal */
        int root = generateGraph(parent, n);
 
        // System.exit(0);
 
        // triggering dfs for traversal over graph
        DFS(root, parent);
 
        int count = 0;
 
        // Calculation of number of isosceles triangles
        for (int i = 0; i < n; ++i) {
            count += min(right_down[i], right_up[i]);
            count += min(left_down[i], left_up[i]);
            count += min(left_down[i], right_down[i]);
        }
        System.out.println("Number of isosceles triangles "
                           + "in the given binary tree are "
                           + Integer.toString(count));
 
        System.exit(0);
    }
}




''' Python3 program for calculating number of
isosceles triangles present in a binary tree '''
 
MAX_SZ = int(1e5)
 
''' Data Structure used to store
  Binary Tree in form of Graph '''
graph = {}
 
# Data variables
right_down = MAX_SZ*[0]
left_down = MAX_SZ*[0]
right_up = MAX_SZ*[0]
left_up = MAX_SZ*[0]
 
''' Utility function used to
    start a DFS traversal over a node '''
def DFS(u, parent):
 
    if u in graph:
        graph[u].sort()
 
    if parent[u] != -1:
        if u in graph and len(graph[parent[u]]) > 1:
            ''' check if current node is
                            left child of its parent '''
            if u == graph[parent[u]][0] :
                right_up[u] += right_up[parent[u]] + 1
             
            # current node is right child of its parent
            else:
                left_up[u] += left_up[parent[u]] + 1
 
        else :
            ''' check if current node is left and
                            only child of its parent '''
            right_up[u] += right_up[parent[u]] + 1
         
    if u in graph:
        for i in range(0, len(graph[u])):
 
            v = graph[u][i]
 
            # iterating over subtree
            DFS(v, parent)
 
            # left child of current node
            if i == 0:
                left_down[u] += left_down[v] + 1;
             
            # right child of current node
            else:
                right_down[u] += right_down[v] + 1;
 
 
''' utility function used to generate
                graph from parent array '''
def generateGraph(parent, n):
     
    root = -1
 
    # Generating graph from parent array
    for i in range(0, n):
         
        # check for non-root node
        if parent[i] != -1:
            ''' creating an edge from node with number
             parent[i] to node with number i '''
            if parent[i] not in graph:
                graph[parent[i]] = [i]
            else :
                graph[parent[i]].append(i)
         
        # initializing root
        else :
            root = i
     
    # root of the binary tree
    return root;
 
# Driver Function
if __name__ == '__main__':
 
    n = 10
 
    ''' Parent array used for storing
       parent of each node '''
    parent = [-1, 0, 0, 1, 1, 2, 2, 3, 4, 4]
 
    ''' generateGraph() function generates a graph a
    returns root of the graph which can be used for
     starting DFS traversal '''
    root = generateGraph(parent, n)
         
    # triggering dfs for traversal over graph
    DFS(root, parent)
 
    count = 0
 
    # Calculation of number of isosceles triangles
    for i in range(0, n):
        count += min(right_down[i], right_up[i])
        count += min(left_down[i], left_up[i])
        count += min(left_down[i], right_down[i])
     
    print("Number of isosceles triangles "
            + "in the given binary tree are "
            + str(count))




/* C# program for calculating number of
isosceles triangles present in a binary tree */
using System;
using System.Collections.Generic;
using System.Linq;
 
class Isosceles_triangles
{
 
    static int MAX_SZ = (int)1e5;
 
    /* Data Structure used to store
    Binary Tree in form of Graph */
    static List<int>[] graph;
 
    // Data variables
    static int[] right_down = new int[MAX_SZ];
    static int[] left_down = new int[MAX_SZ];
    static int[] right_up = new int[MAX_SZ];
    static int[] left_up = new int[MAX_SZ];
 
    /* Utility function used to
    start a DFS traversal over a node */
    public static void DFS(int u, int[] parent)
    {
 
        if (graph[u] != null)
            graph[u].Sort();
 
        if (parent[u] != -1)
        {
            if (graph[parent[u]].Count > 1)
            {
                /* check if current node is
                                left child of its parent */
                if (u == graph[parent[u]][0])
                {
                    right_up[u] += right_up[parent[u]] + 1;
                }
                 
                // current node is right child of its parent
                else
                {
                    left_up[u] += left_up[parent[u]] + 1;
                }
            }
             
            /* check if current node is left and
                                only child of its parent */
            else
            {
                right_up[u] += right_up[parent[u]] + 1;
            }
        }
 
        if (graph[u] == null)
            return;
 
        for (int i = 0; i < graph[u].Count; ++i)
        {
 
            int v = graph[u][i];
 
            // iterating over subtree
            DFS(v, parent);
 
            // left child of current node
            if (i == 0)
            {
                left_down[u] += left_down[v] + 1;
            }
            // right child of current node
            else
            {
                right_down[u] += right_down[v] + 1;
            }
        }
    }
 
    static int min(int a, int b)
    {
        return (a < b) ? a : b;
    }
 
    /* utility function used to generate
                    graph from parent array */
    public static int generateGraph(int[] parent, int n)
    {
 
        int root = -1;
 
        graph = new List<int>[n];
 
        // Generating graph from parent array
        for (int i = 0; i < n; ++i)
        {
 
            // check for non-root node
            if (parent[i] != -1)
            {
                /* creating an edge from node with number
                parent[i] to node with number i */
                if (graph[parent[i]] == null)
                {
                    graph[parent[i]] = new List<int>();
                }
                graph[parent[i]].Add(i);
                // Console.WriteLine(graph);
            }
             
            // initializing root
            else
            {
                root = i;
            }
 
            // Initializing necessary data variables
            left_up[i] = 0;
            right_up[i] = 0;
            left_down[i] = 0;
            right_down[i] = 0;
        }
         
        // root of the binary tree
        return root;
    }
 
    // Driver Function
    public static void Main(String[] args)
    {
        int n = 10;
 
        /* Parent array used for storing
        parent of each node */
        int[] parent = new int[] { -1, 0, 0, 1, 1, 2, 2, 3, 4, 4 };
 
        /* generateGraph() function generates a graph a
        returns root of the graph which can be used for
        starting DFS traversal */
        int root = generateGraph(parent, n);
 
        // System.exit(0);
 
        // triggering dfs for traversal over graph
        DFS(root, parent);
 
        int count = 0;
 
        // Calculation of number of isosceles triangles
        for (int i = 0; i < n; ++i)
        {
            count += min(right_down[i], right_up[i]);
            count += min(left_down[i], left_up[i]);
            count += min(left_down[i], right_down[i]);
        }
        Console.WriteLine("Number of isosceles triangles "
                        + "in the given binary tree are "
                        + count);
    }
}
 
// This code is contributed by Rajput-Ji




<script>
 
// Javascript program for calculating number of
// isosceles triangles present in a binary tree
let MAX_SZ = 1e5;
 
// Data Structure used to store
// Binary Tree in form of Graph
let graph;
 
// Data variables
let right_down = new Array(MAX_SZ);
let left_down = new Array(MAX_SZ);
let right_up = new Array(MAX_SZ);
let left_up = new Array(MAX_SZ);
 
// Utility function used to start
// a DFS traversal over a node
function DFS(u, parent)
{
    if (graph[u] != null)
        graph[u].sort();
 
    if (parent[u] != -1)
    {
        if (graph[parent[u]].length > 1)
        {
             
            // Check if current node is
            // left child of its parent
            if (u == graph[parent[u]][0])
            {
                right_up[u] += right_up[parent[u]] + 1;
            }
             
            // Current node is right child of its parent
            else
            {
                left_up[u] += left_up[parent[u]] + 1;
            }
        }
         
        // Check if current node is left and
        // only child of its parent
        else
        {
            right_up[u] += right_up[parent[u]] + 1;
        }
    }
 
    if (graph[u] == null)
        return;
 
    for(let i = 0; i < graph[u].length; ++i)
    {
        let v = graph[u][i];
 
        // Iterating over subtree
        DFS(v, parent);
 
        // left child of current node
        if (i == 0)
        {
            left_down[u] += left_down[v] + 1;
        }
         
        // right child of current node
        else
        {
            right_down[u] += right_down[v] + 1;
        }
    }
}
 
function min(a, b)
{
    return (a < b) ? a : b;
}
 
// Utility function used to generate
// graph from parent array
function generateGraph(parent, n)
{
    let root = -1;
 
    graph = new Array(n);
 
    // Generating graph from parent array
    for(let i = 0; i < n; ++i)
    {
         
        // Check for non-root node
        if (parent[i] != -1)
        {
             
            // Creating an edge from node with number
            // parent[i] to node with number i
            if (graph[parent[i]] == null)
            {
                graph[parent[i]] = [];
            }
            graph[parent[i]].push(i);
            // System.out.println(graph);
        }
         
        // Initializing root
        else
        {
            root = i;
        }
 
        // Initializing necessary data variables
        left_up[i] = 0;
        right_up[i] = 0;
        left_down[i] = 0;
        right_down[i] = 0;
    }
     
    // Root of the binary tree
    return root;
}
 
// Driver code
let n = 10;
 
// Parent array used for storing
// parent of each node
let parent = [ -1, 0, 0, 1, 1, 2, 2, 3, 4, 4 ];
 
// generateGraph() function generates a graph a
// returns root of the graph which can be used for
// starting DFS traversal
let root = generateGraph(parent, n);
 
// System.exit(0);
 
// Triggering dfs for traversal over graph
DFS(root, parent);
 
let count = 0;
 
// Calculation of number of isosceles triangles
for(let i = 0; i < n; ++i)
{
    count += min(right_down[i], right_up[i]);
    count += min(left_down[i], left_up[i]);
    count += min(left_down[i], right_down[i]);
}
document.write("Number of isosceles triangles " +
               "in the given binary tree are " + count);
 
// This code is contributed by suresh07
 
</script>

Output: 
Number of isosceles triangles in the given binary tree are 9

 

Time Complexity : O(n) 
Auxiliary Space : O(n)
 


Article Tags :