Finding Diameter of a Tree - c++

I have written code for finding the diameter of binary tree. But I am unable to figure out where is it going wrong . The two functions that I have written and their definition are as follows :-
int btree::diameteroftree(node* leaf)
{
if (leaf==NULL)
return 0;
int lheight = hieghtoftree(leaf->left);
int rheight = hieghtoftree(leaf->right);
int ldiameter = diameteroftree(leaf->left);
int rdiameter = diameteroftree(leaf->right);
return max(lheight + rheight + 1,max(ldiameter,rdiameter));
}
int btree::hieghtoftree(node* leaf)
{
int left=0,right=0;
if(leaf==NULL)
return -1;
else
{
left=hieghtoftree(leaf->left);
right=hieghtoftree(leaf->right);
if(left > right)
return left +1;
else
return right+1;
}
}
I am unable to figure out where am I going wrong here . Can someone let me know ...

You want to return the number of nodes on the longest path. Therefore, the problem in your algorithm is this line:
return max(lheight + rheight + 1,max(ldiameter,rdiameter));
where
rootDiameter = lheight + rheight + 1
is the length of the path from the deepest node of the left tree to the deepest node of the right tree. However, this calculation is not correct. A single node returns a height of 0, so it will not be counted. You have two options:
Change hieghtoftree to return the number of nodes on the deepest path and not the number of "hops"
Address this problem in your summation
.
return max(lheight + rheight + 3,max(ldiameter,rdiameter));

In a directed, rooted tree, there is always at most one path between any pair of nodes and the longest path to any node always starts at the root. It follows that the diameter is simply the height of the entire tree height(root), which can be computed with the recursion
height(leaf) = 0
height(node) = max(height(node.left), height(node.right)) + 1
EDIT: the page you link to in the comment describes the diameter of an undirected tree. You need a different tree representation, e.g. an adjacency matrix.

Consider a 3-node tree with root R and 2 leaves L1, L2. Then heightoftree(L1) == heightoftree(L2) == -1. Diameteroftree(R) would therefore be (-1)+(-1)+1 = -1 ?!?
I suggest return -1; --> return 0;
and
return max(lheight + rheight + 1,max(ldiameter,rdiameter)); --> return max(lheight + rheight + 2,max(ldiameter,rdiameter));
The result would be the number of edges on the path. If you count the number of nodes, then add one or subtract one from the final result according to your need.

Related

How to optimize this graph/tree problem counting distance between two nodes in C++?

Problem is to find sum of distance between two nodes in a tree
INPUT: 6 [[0,1],[0,2],[2,3],[2,4],[2,5]]
shows nodes
OUTPUT: [8,12,6,10,10,10]
Explanation: The tree is shown above.
We can see that dist(0,1) + dist(0,2) + dist(0,3) + dist(0,4) + dist(0,5)
equals 1 + 1 + 2 + 2 + 2 = 8.
Hence, answer[0] = 8, and so on.
This is my code, I have solved it but this gives TLE and unable to optimize this solution
How I can optimize this graph problem.
class Solution {
public:
vector<int> sumOfDistancesInTree(int n, vector<vector<int>>& edges) {
vector<int> g[n];
map<pair<int,int>,int> m;
for(auto i:edges){
g[i[0]].push_back(i[1]);
g[i[1]].push_back(i[0]);
}
for(int i=0;i<n;i++){
queue<int> q;
q.push(i);
vector<bool> vis(n,0);
vis[i]=1;
int incr=1;
while(!q.empty()){
int k=q.size();
while(k--){
int t=q.front();q.pop();
for(int j=0;j<g[t].size();j++){
if(!vis[g[t][j]] && g[t][j]!=i){
m[{i,g[t][j]}]+=incr;
q.push(g[t][j]);
vis[g[t][j]]=1;
}
}
}
incr++;
}
}
vector<int> res(n,0);
for(auto i:m){
res[i.first.first]+=i.second;
}
return res;
}
};
As I can see you are using bfs for every node to find the distance.
What you can do is use dynamic programming
Follow the steps below to solve the problem
Initialize a vector dp to store the sum of the distances from each node i to all the leaf nodes of the tree.
Initialize a vector leaves to store the count of the leaf nodes in the sub-tree of node i considering 1 as the root node.
Find the sum of the distances from node i to all the leaf nodes in
the sub-tree of i considering 1 as the root node using a modified
Depth First Search Algorithm.
Let node a be the parent of node i
leaves[a] += leaves[i] ;
dp[a] += dp[i] + leaves[i]
Use the re-rooting technique to find the distance of the remaining
leaves of the tree that are not in the sub-tree of node i. To
calculate these distances, use another modified Depth First Search
(DFS) algorithm to find and add the sum of the distances of leaf
nodes to node i.
Let a be the parent node and i be the child node, then
Let the number of leaf nodes outside the sub-tree i that are present in the sub-tree a be L
L = leaves[a] – leaves[i] ;
dp[i] += ( dp[a] – dp[i] ) + ( L – leaves[i] ) ;
leaves[i] += L ;

Red-Black Tree Height using Recursion

I have these following methods to get the height of a red black tree and this works (I send the root). Now my question is, how is this working? I have drawn a tree and have tried following this step by step for each recursion call but I can't pull it off.
I know the general idea of what the code is doing, which is going through all the leaves and comparing them but can anyone give a clear explanation on this?
int RedBlackTree::heightHelper(Node * n) const{
if ( n == NULL ){
return -1;
}
else{
return max(heightHelper(n->left), heightHelper(n->right)) + 1;
}
}
int RedBlackTree::max(int x, int y) const{
if (x >= y){
return x;
}
else{
return y;
}
}
Well, the general algorithm to find the height of any binary tree (whether a BST,AVL tree, Red Black,etc) is as follows
For the current node:
if(node is NULL) return -1
else
h1=Height of your left child//A Recursive call
h2=Height of your right child//A Recursive call
Add 1 to max(h1,h2) to account for the current node
return this value to parent.
An illustration to the above algorithm is as follows:
(Image courtesy Wikipedia.org)
This code will return the height of any binary tree, not just a red-black tree. It works recursively.
I found this problem difficult to think about in the past, but if we imagine we have a function which returns the height of a sub-tree, we could easily use that to compute the height of a full tree. We do this by computing the height of each side, taking the max, and adding one.
The height of the tree either goes through the left or right branch, so we can take the max of those. Then we add 1 for the root.
Handle the base case of no tree (-1), and we're done.
This is a basic recursion algorithm.
Start at the base case, if the root itself is null the height of tree is -1 as the tree does not exist.
Now imagine at any node what will be the height of the tree if this node were its root?
It would be simply the maximum of the height of left subtree or the right subtree (since you are trying to find the maximum possible height, so you have to take the greater of the 2) and add a 1 to it to incorporate the node itself.
That's it, once you follow this, you're done!
As a recursive function, this computes the height of each child node, using that result to compute the height of the current node by adding + 1 to it. The height of any node is always the maximum height of the two children + 1. A single-node case is probably the easiest to understand, since it has a height of zero (0).
A
Here the call stack looks like this:
height(A) =
max(height(A->left), height(A->right)) + 1
Since both left and right are null, both return (-1), and therefore this reduces to
height(A) = max (-1, -1) + 1;
height(A) = -1 + 1;
height(A) = 0
A slightly more complicated version
A
B C
D E
The recursive calls we care about are:
height(A) =
max(height(B), height(C)) + 1
height(B) =
max(height(D), height(E)) + 1
The single nodes D, E, and C we already know from our first example have a height of zero (they have no children). therefore all of the above reduces to
height(A) = max( (max(0, 0) + 1), 0) + 1
height(A) = max(1, 0) + 1
height(A) = 1 + 1
height(A) = 2
I hope that makes at least a dent in the learning curve for you. Draw them out on paper with some sample trees to understand better if you still have doubts.

Understanding Balance Factors/Node Height for AVL rotations

So I am having a hard time understanding how to balance AVL trees. I understand the rotation stuff, but I can't figure out how to find the balance factor of node heights, for example:
http://i.imgur.com/yh5zNIl.png
Can anyone explain to me how we actually find the balance factor for EACH node?
I know if the height of [(left subtree) - (right subtree)] is not within (-1<= x <= 1) then its unbalanced...but I can't figure how to find "x".
(edit: I don't need code, I just want to understand how to find BF).
If I understand your question correctly, you want to know how to maintain the balance-factor of a given node. The best way to keep the track is when doing an "insert" in the tree. This is because you know whether your new node is going to the left or the right side of the "current" node. When it goes to the left, you decrement the balance and when it goes to the right, you increment the balance. The idea is to have the tree already balanced before you exit the "insert" method.
Another approach I have seen is NOT doing the balancing during the "insert". You simply insert like you would in BST. After the insert, you begin your balancing act where you get the left subtree and right subtree height at each node and start shuffling pointers. This is not a good approach since you incur O(logn) for every node in finding the height and since you would do that for every node, it results into n*O(logn).
I am posting the "insert" method that I once wrote that keeps the tree balanced at every insert and does NOT compute the height separately at any point during the insert. See if it helps:
Node*
AVL::insert(Node* node, int key, int value)
{
if(node == NULL)
node = new Node(key, value);
else if (key <= node->key)
{
node->balance--;
node->left = insert(node->left, key, value);
}
else if (key > node->key)
{
node->balance++;
node->right = insert(node->right, key, value);
}
// Right Tree Heavy
if (node->balance == 2)
{
// Left tree unbalanced
if (node->right && node->right->balance == 1)
{
// LL
node = singleLeftRotation(node);
node->balance = 0;
node->left->balance = 0;
}
if (node->right && node->right->balance == -1)
{
// LR
int nodeRLBalance = node->right->left->balance;
node = doubleLeftRotation(node);
node->balance = 0;
node->left->balance = nodeRLBalance == 1 ? -1 : 0;
node->right->balance = nodeRLBalance == -1 ? 1 : 0;
}
}
// Left Tree Heavy
if (node->balance == -2)
{
// Right tree unbalanced
if (node->left && node->left->balance == -1)
{
// RR
node = singleRightRotation(node);
node->balance = 0;
node->right->balance = 0;
}
if (node->left && node->left->balance == 1)
{
// RL
int nodeLRBalance = node->left->right->balance;
node = doubleRightRotation(node);
node->balance = 0;
node->left->balance = nodeLRBalance == 1 ? -1 : 0;
node->right->balance = nodeLRBalance == -1 ? 1 : 0;
}
}
return node;
}
The balance factor of a node is the difference of the height of it's left and right descendant nodes.
The balance factor is defined by some as:
balance = node.left.height - node.right.height
and by other as:
balance = node.right.height - node.left.height
so if you want to understand the balance of some nodes in a graph you have to know how they define the balance factor.
For example wikipedia defines it as node.left.height - node.right.height
and you can see that the formula results matches the node balance factors
Avl Tree Balance of Nodes Example
X is the height of the left subtree - the height of the right subtree.
If the left subtree has a max height of three and the right subtree has a max height of two, then the balance factor would be
3 - 2 = Balance Factor of 1 (Left Heavy)
The other way around:
2 - 3 = Balance Factor of -1 (Right Heavy)
If both are the same:
3 - 3 = Balance Factor of 0 (Even Heavy)
A tree becomes unbalanced when the difference between the heights is greater than 1 or less than -1.
5 - 3 = Balance Factor of 2 (UNBALANCED!)
3 - 5 = Balance Factor of -2 (UNBALANCED!)
this image will probably help you. Unbalanced AVL tree has a violation in the E-node
unbalanced AVL tree

find sum of maximum possible triangular chord

I am having a binary tree
2
/ \
3 4
/ \ \
5 1 8
/ \ / \
1 6 9 2
\
4
i want to find the maximum possible triangular chord info sum of nodes ( between any two leaves and a node having both left and right child ) in the given tree.
a triangular chord will be
for triangular chord :
just imagine a line between any two leaves, go upward towards root, find a common parent (that can be parent, grandparent, grandgrandparent or even the root itself). While moving upwards, for each leaf ( for any leaf either we have to go upward only left left left .... and so OR either only right right right right .. and so) means ( left leaf will only move right upward only and right leaf will move left upward only..... So for any single leaf, we can not move in both direction while moving upwards).. Now we get a triangular shape.. in which a side may contain any no. of nodes/links possible.. NOW, if that triangular shape does not contain any extra internal branches. that triangular shape will be a triangular chord.
Do remember that every leaf node is also always a triangular chord (It is just to create the default cases if the binary tree do not have any triangular shaped chord)
now
maximum triangular chord will be that triangular chord
which have maximum total in sum of all its node info.
we are required to return that maximum total.
If we do not have triangular shaped chord..
then we have to return the leaf with maximum info.
for example
8
/ \
2 3
\
3
is a triangular chord
8
/ \
2 3
\ \
4 1
only subtree with single node 4 will be maximum triangular chord (as its sum is greater than another triangular chord with single node 1) Not the whole tree will be triangular chord
8
/ \
2 3
/ \
4 3
is a triangular chord
so the solution of the very first tree on the first line of question is
8+9+2+4 = 23
i am badly trapped in this problem.
I have a rough approach
I will recursively call leftchild as root of subtree and find the left maximum triangular chord sum
then same for rightchild as root of subtree.
add the max of leftmax and rightmax, and the add to rood node and return
in c++ mycode is :
int maxtri(node* n)
{
if(n)
{
lsum = maxtri(n->left);
rsum = maxtri(n->right);
k = maxof(lsum,rsum);
return (n->info + k);
}
}
edit : my another recursive approach
int l =0, r =0;
int maxtri(node* n)
{
if (n == NULL) return 0;
if (!(n->left) && !(n->right)) return n->info;
if ((n->left) && (n->right))
{
l = maxtri(n->left);
r = maxtri(n->right);
}
if ((n->left) && !(n->right))
{
l = l + maxtri(n->left);
}
if (!(n->left) && (n->right))
{
r = r + maxtri(n->right);
}
return (l+r+n->info);
}
i have doubt on my approach.
can anyone give another solution.??
What about this logic:
For each node traverse the left portion and right portion, if you find any branches then don't consider this node in your calculation else consider this. Moreover, for the part of calculation node should have left & right nodes or it should be leaf node.
Note: I have not tested it properly but i believe it should work.
// Node by Node traverse the tree
void addSum(Node *head, vector<int>& sum)
{
if (head == NULL)
return;
else {
int s = traverseThisNode(head);
sum.push_back(s); // Add to vector
addSum(head->left, sum);
addSum(head->right, sum);
}
}
// For each node traverse left & right
int traverseThisNode(Node *head)
{
if (head && head->left && head->right) {
Node *temp = head; // To traverse right portion of this node
int sum = head->value;
while(head->left) { // Traverse right
head = head->left;
sum = sum + head->value;
if (head->right) { // Condition to check if there is any branching
sum = 0;
break;
}
}
while(temp->right && sum != 0) { // Traverse Right now
temp = temp->right;
sum = sum + temp->value;
if (temp->left) { // Condition to check if there is any branching
sum = 0;
break;
}
}
return sum;
} else if (head && !head->left && !head->right) {
return head->value; // To add leaf node
}
return 0;
}
Now you have vector containing all the value of triangular in the tree, traverse it and
find the maximum.
int maximum()
{
// Traverse the vector "sum" & find the maximum
}
I write the pseudocode for my approach, as far as I have understood the question.
Max = min_value; //possibly 0 if no negative value is allowed for nodes.
sum = 0;
for each node in the tree
temp = node;
sum+= temp->data //collects data at the current level, the current level may be leaf too.
Until temp->left is not null, // Traversing uni-directionally to the left most deep and collecting data.
temp = temp->left
sum+=temp->data
Until temp->right is not null, // Traversing uni-directionally to the right most deep and collecting data.
temp = temp->right
sum+= temp->data
if(sum > Max)
Max = sum;
sum = 0;
print Max;

How to get the longest path in a DAG starting at a fixed node?

I want to know how to get the longest path in a DAG starting from the node 0(the smallest node)
I searched wiki and got the following algorithm:
algorithm dag-longest-path is
input:
Directed acyclic graph G
output:
Length of the longest path
length_to = array with |V(G)| elements of type int with default value 0
for each vertex v in topOrder(G) do
for each edge (v, w) in E(G) do
if length_to[w] <= length_to[v] + weight(G,(v,w)) then
length_to[w] = length_to[v] + weight(G, (v,w))
return max(length_to[v] for v in V(G))
but I don't know how to implement it, of course the following code I wrote doesn't work:(topo is the topological sorted nodes)
public static int longestPath(int[] topo){
int[] dist = new int[topo.length];
for(int i:topo){
if(isArc(node,i)){
if(dist[i]<dist[node]+1){
dist[i] = dist[node] + 1;
}
}
}
return getMax(dist);
}
How should I do? Thanks!
Besides, could you give me an algorithm to calculate the number of different paths from 0 to n-1?