Finding the lexicographically smallest diameter in a binary tree

Given a binary tree where node values are lowercase alphabets, the task is to find the lexicographically smallest diameter. A diameter is the longest path between any two leaf nodes, hence, there can be multiple diameters in a Binary Tree. The task is to print the lexicographically smallest diameter among all possible diameters.

Examples:

Input:          
        a
      /   \
    b       c
  /  \     /  \
 d   e    f    g
Output: Diameter: 5
Lexicographically smallest diameter: d b a c f
Explanation:
Note that there are many other paths 
exist like {d, b, a, c, g}, 
{e, b, a, c, f} and {e, b, a, c, g} 
but {d, b, a, c, f} 
is lexicographically smallest

Input:          
        k
      /   \
    e       s
  /  \       
 g   f    
Output: Diameter: 4
Lexicographically smallest diameter: f e k s
Explanation:
Note that many other paths 
exist like {g, e, k, s} 
{s, k, e, g} and {s, k, e, f} 
but {f, e, k, s} is 
lexicographically smallest

Approach:
The approach is similar to finding diameter as discussed in the previous post. Now comes the part of
printing the longest path with maximum diameter and lexicographically smallest.



Steps:

  • Custom compare function returns lexicographical smallest vector is made.
  • Six kinds of vector are been maintained which contains
    the left subtree ( of a node) nodes in leftdiameter
    the right subtree (of a node) nodes in rightdiameter
    nodes occuring in the left height (of a node)
    nodes occuring in the right height (of a node)
    heightv vector contains contains the nodes occuring the path of max height
    dia vector contains contains the nodes occuring the path of max height
  • Rest part is explained in the comments of code and it will be difficult to explain here in words

Below is the implementation of above approach:

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
  
// Binary Tree Node
struct node {
    char data;
    node *left, *right;
};
  
// Utility function to create a new node
node* newNode(char data)
{
    node* c = new node;
    c->data = data;
    c->left = c->right = NULL;
    return c;
}
  
// Function to compare and return
// lexicographically smallest vector
vector<node*> compare(vector<node*> a, vector<node*> b)
{
    for (int i = 0; i < a.size() && i < b.size(); i++) {
        if (a[i]->data < b[i]->data) {
            return a;
        }
        if (a[i]->data > b[i]->data) {
            return b;
        }
    }
  
    return a;
}
  
// Function to find diameter
int diameter(node* root, int& height, vector<node*>& dia,
             vector<node*>& heightv)
{
    // If root is null
    if (!root) {
        height = 0;
        return 0;
    }
  
    // Left height and right height
    // respectively
    int lh = 0, rh = 0;
  
    // Left tree diameter and
    // right tree diameter
    int ld, rd;
  
    vector<node*> leftdia;
    vector<node*> rightdia;
    vector<node*> leftheight;
    vector<node*> rightheight;
  
    // Left subtree diameter
    ld = diameter(root->left, lh, leftdia, leftheight);
  
    // Right subtree diameter
    rd = diameter(root->right, rh, rightdia, rightheight);
  
    // If left height is more
    // than right tree height
    if (lh > rh) {
  
        // Add current root so lh + 1
        height = lh + 1;
  
        // Change vector heightv to leftheight
        heightv = leftheight;
  
        // Insert current root in the path
        heightv.push_back(root);
    }
  
    // If right height is
    // more than left tree height
    else if (rh > lh) {
  
        // Add current root so rh + 1
        height = rh + 1;
  
        // Change vector heightv to rightheight
        heightv = rightheight;
  
        // Insert current root in the path
        heightv.push_back(root);
    }
  
    // Both height same compare
    // lexicographically now
    else {
  
        // Add current root so rh + 1
        height = rh + 1;
  
        // Lexigcographical comparison between two vectors
        heightv = compare(leftheight, rightheight);
  
        // Insert current root in the path
        heightv.push_back(root);
    }
  
    // If distance of one leaf node to another leaf
    // containing the root is more than the left
    // diameter and right diameter
    if (lh + rh + 1 > max(ld, rd)) {
  
        // Make dia equal to leftheight
        dia = leftheight;
  
        // Add current root into it
        dia.push_back(root);
  
        for (int j = rightheight.size() - 1; j >= 0; j--) {
            // Add right tree (right to root) nodes
            dia.push_back(rightheight[j]);
        }
    }
  
    // If either leftdiameter containing the left
    // subtree and root or rightdiameter containg
    // the right subtree and root is more than
    // above lh+rh+1
    else {
  
        // If diameter of left tree is
        // greater our answer vector i.e
        // dia is equal to leftdia then
        if (ld > rd) {
            dia = leftdia;
        }
  
        // If both diameter
        // same check lexicographically
        else if (ld == rd) {
            dia = compare(leftdia, rightdia);
        }
  
        // If diameter of right tree
        // is greater our answer vector
        // i.e dia is equal to rightdia then
        else {
            dia = rightdia;
        }
    }
  
    return dia.size();
}
  
// Driver code
int main()
{
    node* root = newNode('a');
    root->left = newNode('b');
    root->right = newNode('c');
    root->left->left = newNode('d');
    root->left->right = newNode('e');
    root->right->left = newNode('f');
    root->right->right = newNode('g');
  
    int height = 0;
    vector<node *> dia, heigh;
    cout << "Diameter is: " << diameter(root, height,
                                        dia, heigh)
         << endl;
  
    // Printing the lexicographically smallest diameter
    cout << "Lexicographically smallest diameter:" << endl;
    for (int j = 0; j < dia.size(); j++) {
        cout << dia[j]->data << " ";
    }
  
    return 0;
}

chevron_right


Output:

Diameter is: 5
Lexicographically smallest diameter:
d b a c f


My Personal Notes arrow_drop_up

Competitive Programmer, Full Stack Developer, Technical Content Writer, Machine Learner

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.




Article Tags :
Practice Tags :


Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.