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. 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 the 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 occurring in the left height (of a node)
nodes occurring in the right height (of a node)
heightv vector contains the nodes occurring the path of max height
dia vector contains the nodes occurring 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 the above approach:
CPP
// 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; // Lexicographical 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 containing // 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, heightv; cout << "Diameter is: " << diameter(root, height, dia, heightv) << 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; } |
Output:
Diameter is: 5 Lexicographically smallest diameter: d b a c f
Please Login to comment...