Calculating the height of a binary tree - data-structures

I need help with the theory on calculating the height of a binary tree, typically the notation.
I have read the following article:
Calculating height of a binary tree
And one of the posts gives the following notation:
height(node) = max(height(node.L), height(node.R)) + 1
Let's assume I have the following binary tree:
10
/ \
5 30
/ \ / \
4 8 28 42
Do I therefore calculate the max value on the left node (8) and the max node on the right (42) and then add 1? I don't quite understand how this notation works in order to calculate the height of the tree.

I'll try to explain how this recursive algorithm works:
height(10) = max(height(5), height(30)) + 1
height(30) = max(height(28), height(42)) + 1
height(42) = 0 (no children)
height(28) = 0 (no children)
height(5) = max(height(4), height(8)) + 1
height(4) = 0 (no children)
height(8) = 0 (no children)
So if you want to calculate height(10), you have to expand the recursion down, and than substitute results backwards.
height(5) = max(0, 0) + 1
height(30) = max(0, 0) + 1
height(10) = max(1, 1) + 1
height(10) = 2
EDIT:
As noted in comments:
height of binary tree = number of layers - 1
Therefore there should be assumption that height of empty node is equal to -1 i.e:
height(empty) = -1
or
height(null) = -1
this way
height(42) = max(height(null), height(null)) + 1
height(42) = max(-1, -1) + 1
height(42) = -1 + 1
height(42) = 0
I have corrected calculation above.

Height of the tree is the length of the path from the root to the deepest node in the tree. Here is the shortest algo to do so
int height(Node root){
if(root == null )
return 0;
return 1+max{height(root.left), height(root.right)};
}

Do u know the definition of node's height? I would answer it as the farthest distance to a reachable leaf(so all leaf have height 0)...now try to find the height of every node from bottom to top..that would your algo..

Find out the root node, then look for the longest path that u can cover(means the maximum number of node you can cover in that path),
if u get that path, then check how many branches or edges you have covered,
the total number of branches you have covered is the height of the tree

Repeated Question
Despite being good introductions to recursion, I'm a bit surprised by all the incorrect answers as to the height of a binary tree, so I thought I'd offer the correct solution. I did some digging and this question is answered properly here: https://stackoverflow.com/a/2597754/5567854.
Reference
According to Wikipedia, "A tree consisting of only a root node has a height of 0", not 1 as the other answers state. Therefore, with the example from the question:
10
/ \
5 30
/ \ / \
4 8 28 42
If 10 was the root node to find the height of that tree, then the height is 2, not 3.
Correct Code
This solution is one of many possible solutions in C Language...
size_t binary_tree_height(const binary_tree_t *tree)
{
size_t r, l, height = 0;
if (tree)
{
r = tree->right ? binary_tree_height(tree->right) + 1 : 0;
l = tree->left ? binary_tree_height(tree->left) + 1 : 0;
height += (r > l ? r : l);
}
return (height);
}

The highest number of nodes that is possible in a way starting from the first node (ROOT) to a leaf node is called the height of tree. The formula for finding the height of a tree h=i(max)+1 , where h is the height and I is the max level of the tree

#include<stdio.h>
#include<stdlib.h>
/* A binary tree node has data, pointer to left child
and a pointer to right child */
struct node
{
int data;
struct node* left;
struct node* right;
};
/* Compute the "maxDepth" of a tree -- the number of
nodes along the longest path from the root node
down to the farthest leaf node.*/
int maxDepth(struct node* node)
{
if (node==NULL)
return 0;
else
{
/* compute the depth of each subtree */
int lDepth = maxDepth(node->left);
int rDepth = maxDepth(node->right);
/* use the larger one */
if (lDepth > rDepth)
return(lDepth+1);
else return(rDepth+1);
}
}
/* Helper function that allocates a new node with the
given data and NULL left and right pointers. */
struct node* newNode(int data)
{
struct node* node = (struct node*)
malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return(node);
}
int main()
{
struct node *root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
printf("Hight of tree is %d", maxDepth(root));
getchar();
return 0;
}

You can use the recursive approach.
int height(Node root) {    return root==null ? 0 : Math.max(height(root.left), height(root.right)) +1;}

Recursive approach for height of binary tree as below in user defined binary tree in Java-
class Node
{
int data;
Node left, right;
public Node(int item)
{
data = item;
left = right = null;
}
boolean isLeaf() { return left == null ? right == null : false; }
}
public class BinaryTree {
Node root;
public BinaryTree() {
root = null;
}
public static void main(String args[])
{
BinaryTree tree = new BinaryTree();
tree.root= new Node(1);
tree.root.left= new Node(2);
tree.root.right= new Node(3);
tree.root.left.left= new Node(4);
tree.root.left.right= new Node(5);
tree.root.right.left = new Node(6);
tree.root.right.right = new Node(7);
tree.root.right.left.left = new Node(8);
tree.root.right.left.right = new Node(9);
System.out.println("\n Height of tree is : "+tree.height(tree.root));
}
/*Height of Binary tree*/
public int height(Node root) {
if (root == null)
return 0;
else {
int lHeight = height(root.left);
int rHeight = height(root.right);
if (lHeight > rHeight)
return (lHeight + 1);
else return (rHeight + 1);
}
}
}
With the above code you can easily create binary tree without using library in java.

C enthousiasts, feel free to have a read at this article:
http://www.csegeek.com/csegeek/view/tutorials/algorithms/trees/tree_part3.php
I re-aranged the C code to PHP:
function getTreeHeight($node) {
if (!isset($node['left']) && !isset($node['right'])) {
return 0;
}
$leftHeight = getTreeHeight($node['left']);
$rightHeight = getTreeHeight($node['right']);
if ($leftHeight > $rightHeight) {
return $leftHeight + 1;
} else {
return $rightHeight + 1;
}
}
$array = array(
'value' => 5,
'left' => array(
'value' => 2,
'left' => array(
'value' => 1,
),
'right' => array(
'value' => 4
),
),
'right' => array(
'value' => 11,
'left' => array(
'value' => 7
),
'right' => array(
'value' => 23,
'left' => array(
'value' => 16
),
'right' => array(
'value' => 34
),
),
)
);
echo getTreeHeight($array); //output 3

Related

Is it possible to implement binary heap without using additional data structure (e.g. array, linked list)

Can I implement a binary heap by only using a TreeNode inferface (has children, or left/right, or/and parent.. something like this)?
I want to not rely on using array or linked list.
If I don't use array or linked list, I have a trouble inserting the next element in the correct place & keep it a complete binary tree (all non-leaf nodes are full). Also have trouble taking out the root and re-heapifying.
One key observation is this:
The path from the root to the last leaf in a complete binary tree is represented by the binary representation of the size of the tree (number of nodes in the tree).
For instance, this tree has 9 nodes.
1
/ \
4 2
/ \ / \
6 5 3 7
/ \
9 8
9 in binary is 1001. Skipping the most significant "1", this can be read from left-to-right as 0, 0, 1 or "left-left-right". That describes indeed the path from root to the leaf node with value 8!
The same principle holds for when you need to find the insertion point for a new node. Then first increase the size, so this becomes 10 in the example. The binary representation is 1010. Skipping the first digit, this represents "left-right-left". The last direction ("left") gives information about the edge that must be added. And indeed, "left-right" leads us to the node with value 5, and a new node has to be inserted as left-child of that node!
To restore the heap property after an insertion, keep track of the path towards the newly inserted leaf (for example, when coming back out of a recursive function), and wind that path back, each time verifying the heap property, and swapping values when necessary.
Similarly, for an extraction of the root value: first find the node to delete (see above), delete that node and assign the deleted value to the root node. Then sift down the heap to restore the heap property.
Here is an implementation in plain JavaScript -- it should be easy to port this to any other language:
class Node {
constructor(value) {
this.value = value;
this.left = this.right = null;
}
swapValueWith(other) { // We don't swap nodes, just their values
let temp = this.value;
this.value = other.value;
other.value = temp;
}
}
class HeapTree {
constructor() {
this.root = null;
this.size = 0;
}
insert(value) {
this.size++;
if (this.root == null) {
this.root = new Node(value);
} else { // Use the binary representation of the size to find insertion point
this.insertRecursive(this.root, 1 << (Math.floor(Math.log2(this.size)) - 1), value);
}
}
insertRecursive(node, bit, value) {
let side = this.size & bit;
let child;
if (side > 0) {
if (bit == 1) node.right = new Node(value);
child = node.right;
} else {
if (bit == 1) node.left = new Node(value);
child = node.left;
}
if (bit > 1) this.insertRecursive(child, bit>>1, value)
if (node.value > child.value) node.swapValueWith(child); // sift up
}
extract() {
if (this.root == null) return; // Nothing to extract
let value = this.root.value; // The value to return
if (this.size == 1) {
this.root = null;
} else {
// Use the binary representation of the size to find last leaf -- to be deleted
this.root.value = this.deleteRecursive(this.root, 1 << (Math.floor(Math.log2(this.size)) - 1));
// Sift down
let node = this.root;
while (true) {
let minNode = node;
if (node.left != null && node.left.value < minNode.value) minNode = node.left;
if (node.right != null && node.right.value < minNode.value) minNode = node.right;
if (minNode === node) break;
node.swapValueWith(minNode);
node = minNode;
}
}
this.size--;
return value;
}
deleteRecursive(node, bit) {
let side = this.size & bit;
let child;
if (side > 0) {
child = node.right;
if (bit == 1) node.right = null;
} else {
child = node.left;
if (bit == 1) node.left = null;
}
return bit == 1 ? child.value : this.deleteRecursive(child, bit>>1);
}
}
// Demo
let heap = new HeapTree();
for (let value of [4,2,5,8,7,9,0,3,1,6]){
heap.insert(value);
}
// Output the values in sorted order:
while (heap.root != null) {
console.log(heap.extract());
}

How to derive the proof of this formula for getting right child for a binary tree given inorder and preorder traversals?

I'm looking at this question on leetcode. Given two arrays, inorder and preorder, you need to construct a binary tree. I get the general solution of the question.
Preorder traversal visits root, left, and right, so the left child would be current preorder node index + 1. From that value, you can then know how many nodes are on the left of the tree using the inorder array. In the answers, the formula used to get the right child is "preStart + inIndex - inStart + 1".
I don't want to memorize the formula so I'm wondering if there is a proof for this? I went through the discussion board there, but I'm still missing a link.
For Python Only
In Python we can also use pop(0) for solving this problem, even though that's inefficient (it would pass though).
For inefficiency we can likely use deque() with popleft(), however not on LeetCode, because we don't have control over the tree.
class Solution:
def buildTree(self, preorder, inorder):
if inorder:
index = inorder.index(preorder.pop(0))
root = TreeNode(inorder[index])
root.left = self.buildTree(preorder, inorder[:index])
root.right = self.buildTree(preorder, inorder[index + 1:])
return root
For Java and C++, that'd be a bit different just like you said (don't have the proof) but maybe this post would be just a bit helpful:
public class Solution {
public static final TreeNode buildTree(
final int[] preorder,
final int[] inorder
) {
return traverse(0, 0, inorder.length - 1, preorder, inorder);
}
private static final TreeNode traverse(
final int preStart,
final int inStart,
final int atEnd,
final int[] preorder,
final int[] inorder
) {
if (preStart > preorder.length - 1 || inStart > atEnd) {
return null;
}
TreeNode root = new TreeNode(preorder[preStart]);
int inorderIndex = 0;
for (int i = inStart; i <= atEnd; i++)
if (inorder[i] == root.val) {
inorderIndex = i;
}
root.left = traverse(preStart + 1, inStart, inorderIndex - 1, preorder, inorder);
root.right = traverse(preStart + inorderIndex - inStart + 1, inorderIndex + 1, atEnd, preorder, inorder);
return root;
}
}
C++
// The following block might slightly improve the execution time;
// Can be removed;
static const auto __optimize__ = []() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
// Most of headers are already included;
// Can be removed;
#include <cstdint>
#include <vector>
#include <unordered_map>
using ValueType = int;
static const struct Solution {
TreeNode* buildTree(
std::vector<ValueType>& preorder,
std::vector<ValueType>& inorder
) {
std::unordered_map<ValueType, ValueType> inorder_indices;
for (ValueType index = 0; index < std::size(inorder); ++index) {
inorder_indices[inorder[index]] = index;
}
return build(preorder, inorder, inorder_indices, 0, 0, std::size(inorder) - 1);
}
private:
TreeNode* build(
std::vector<ValueType>& preorder,
std::vector<ValueType>& inorder,
std::unordered_map<ValueType, ValueType>& inorder_indices,
ValueType pre_start,
ValueType in_start,
ValueType in_end
) {
if (pre_start >= std::size(preorder) || in_start > in_end) {
return nullptr;
}
TreeNode* root = new TreeNode(preorder[pre_start]);
ValueType pre_index = inorder_indices[preorder[pre_start]];
root->left = build(preorder, inorder, inorder_indices, pre_start + 1, in_start, pre_index - 1);
root->right = build(preorder, inorder, inorder_indices, pre_start + 1 + pre_index - in_start, pre_index + 1, in_end);
return root;
}
};

How to construct a binary tree using a level order traversal sequence

How to construct a binary tree using a level order traversal sequence, for example from sequence {1,2,3,#,#,4,#,#,5}, we can construct a binary tree like this:
1
/ \
2 3
/
4
\
5
where '#' signifies a path terminator where no node exists below.
Finally I implement Pham Trung's algorithm by c++
struct TreeNode
{
TreeNode *left;
TreeNode *right;
int val;
TreeNode(int x): left(NULL), right(NULL), val(x) {}
};
TreeNode *build_tree(char nodes[], int n)
{
TreeNode *root = new TreeNode(nodes[0] - '0');
queue<TreeNode*> q;
bool is_left = true;
TreeNode *cur = NULL;
q.push(root);
for (int i = 1; i < n; i++) {
TreeNode *node = NULL;
if (nodes[i] != '#') {
node = new TreeNode(nodes[i] - '0');
q.push(node);
}
if (is_left) {
cur = q.front();
q.pop();
cur->left = node;
is_left = false;
} else {
cur->right = node;
is_left = true;
}
}
return root;
}
Assume using array int[]data with 0-based index, we have a simple function to get children:
Left child
int getLeftChild(int index){
if(index*2 + 1 >= data.length)
return -1;// -1 Means out of bound
return data[(index*2) + 1];
}
Right child
int getRightChild(int index){
if(index*2 + 2 >= data.length)
return -1;// -1 Means out of bound
return data[(index*2) + 2];
}
Edit:
Ok, so by maintaining a queue, we can build this binary tree.
We use a queue to maintain those nodes that are not yet processed.
Using a variable count to keep track of the number of children added for the current node.
First, create a root node, assign it as the current node.
So starting from index 1 (index 0 is the root), as the count is 0, we add this node as left child of the current node.
Increase count. If this node is not '#', add it to the queue.
Moving to the next index, the count is 1, so we add this as right child of current node, reset count to 0 and update current node (by assigning the current node as the first element in the queue). If this node is not '#', add it to the queue.
int count = 0;
Queue q = new Queue();
q.add(new Node(data[0]);
Node cur = null;
for(int i = 1; i < data.length; i++){
Node node = new Node(data[i]);
if(count == 0){
cur = q.dequeue();
}
if(count==0){
count++;
cur.leftChild = node;
}else {
count = 0;
cur.rightChild = node;
}
if(data[i] != '#'){
q.enqueue(node);
}
}
class Node{
int data;
Node leftChild, rightChild;
}
Note: this should only work for a binary tree and not BST.
we can build this binary tree from level order traversal by maintaining a queue. Queue is used to maintain those nodes that are not yet processed.
Using a variable count(index variable) to keep track of the number of children added for the current node.
First, create a root node, assign it as the current node. So starting from index 1,
index value is 1 means, we will add the next value as left node.
index value is 2 means we will add the next value as right node and index value 2 means that we have added left and right node, then do the same for the remaining nodes.
if arr value is -1
3.a. if index value is 1,i.e., there is no left node then change the index variable to add right node.
3.b. if index value is 2, i.e, there is no right node then we have repeat this step for the remaining.
static class Node{
int data;
Node left;
Node right;
Node(int d){
data=d;
left=null;
right=null;
}
}
public static Node constBT(int arr[],int n){
Node root=null;
Node curr=null;
int index=0;
Queue<Node> q=new LinkedList<>();
for(int i=0;i<n;i++){
if(root==null){
root=new Node(arr[i]);
q.add(root);
curr=q.peek();
index=1;
}else{
if(arr[i]==-1){
if(index==1)
index=2;
else{
q.remove();
curr=q.peek();
index=1;
}
}
else if(index==1){
curr.left=new Node(arr[i]);
q.add(curr.left);
index=2;
}else if(index==2){
curr.right=new Node(arr[i]);
q.add(curr.right);
q.remove();
curr=q.peek();
index=1;
}
}
}
return root;
}
My approach is similar to Pham Trung yet intutive. We would maintain an array of Nodes of given data instead of using a queue. We would do reverse engineering on BFS using queue. because BFS for a tree is basically its Level Order Traversal (LOT).
It is important to note that we should have the NULL childs of an node for the LOT to be unique and the reconstruction of Tree from LOT to be possible.
In this case LOT : 1,2,3,-1,-1,4,-1,-1,5
where I have used -1 instead of '#' to represent NULLs
And Tree is
1
/ \
2 3
/ \ /
-1 -1 4
/ \
-1 5
Here, we can easily see that when 1 is popped from the BFS queue, it pushed its left child
(2) and right child (3) in the queue. Similary, for 2 it pushed -1 (NULL) for both of its children. And the process is continued.
So, we can follow the following pseudo code to generate the tree rooted at LOT[0]
j = 1
For every node in LOT:
if n<=j: break
if node != NULL:
make LOT[j] left child of node
if n<=j+1: break
make LOT[j+1] right child of node
j <- j+2
Finally, C++ code for the same
Class Declaration and Preorder traversal
class Node{
public:
int val;
Node* lft, *rgt;
Node(int x ):val(x) {lft=rgt=nullptr;}
};
void preorder(Node* root) {
if(!root) return;
cout<<root->val<<" ";
preorder(root->lft);
preorder(root->rgt);
}
Restoring Tree from LOT Logic
int main(){
int arr[] = {1,2,3,-1,-1,4,-1,-1,5};
int n = sizeof(arr)/sizeof(int);
Node* brr[n];
for(int i=0;i<n;i++) {
if(arr[i]==-1) brr[i] = nullptr;
else brr[i] = new Node(arr[i]);
}
for(int i=0,j=1;j<n;i++) {
if(!brr[i]) continue;
brr[i]->lft = brr[j++];
if(j<n) brr[i]->rgt = brr[j++];
}
preorder(brr[0]);
}
Output: 1 2 3 4 5

Print the Longest leaf-to-leaf path in a binary tree along with its length

I am solving a problem in which I have to find the longest leaf-to-leaf path in a binary tree along with its length.
for example, if the Binary tree is as follows:
a
/\
b c
/ / \
d e f
/ \ \
g h p
\
k
The longest leaf-to-leaf path would be k-h-d-b-a-c-f-p which is of length 8.
I am calculating the length by recursively finding the length of the left and right sub-tree and then return height_left + height_right + 1 . Is my concept correct?.
Also how should I print the longest leaf-to-leaf path? I just want an idea to proceed.
It seems to me that this algorithm is very close to finding a diameter of a binary tree. Diameter of the tree is the number of nodes on the longest path between two leaves in the tree.
I think you can look here for the implementation: http://www.geeksforgeeks.org/diameter-of-a-binary-tree/ and then adapt it or optimize it's time complexity if you want. But i think O(n) is good enough.
Most answers on the net gives how to find diameter of a tree, i.e
How to find the number of nodes in the longest path.
The only addition is we need to store the nodes which contribute to it.
In recursion, this can be done in two ways.
a) It should be a return type
b) It should be an input parameter which is an object. This object is populated with the result during the course of recursion.
Without the need to print the longest path, we only need to check at every node:
Max of
1) Left node max path
2) Right node max path
c) Current node max path (requires more inputs)
Now, to calculate current node max path, we need more inputs:
Current node max path needs:
1) Max left node height
2) Max right node height
This can either be stored in the node itself (as height parameter) or can be passed with the recursion.
This will only give diameter/length of the longest path.
Now, to get the path printed, we need to store more info which is:
- List<Nodes> pathList - This contains the nodes which form the longest path so far (Note this may not contain the current node).
- List<Nodes> heightList - This contains the nodes which form the longest height from the node to its leaf.
Finally the algo:
//Inputs and Outputs of the method
class Node{
int value;
Node leftchild;
Node rightchild;
}
class ReturnInfo{
ReturnInfo(){
maxpathlen = 0;
maxheight = 0;
pathList = new ArrayList<Node>();
heightList = new ArrayList<Node>();
}
int maxpathlen; //current max path
int maxheight; //current max height
List<Nodes> pathList;
List<Nodes> heightList;
}
//Signature
public ReturnInfo getMaxPath(Node n);
//Implementation
public ReturnInfo getMaxPath(Node n){
//Base case
if(n==null) return new ReturnInfo();
//This is a bottom up recursion. Info will flow from leaves to root.
//So first recurse and then do the work at this node level
//Recurse left & right
ReturnInfo leftReturnInfo = getMaxPath(n.leftchild);
ReturnInfo rightReturnInfo = getMaxPath(n.rightchild);
//Do work in this recursion or for this node
ReturnInfo retInfo = new ReturnInfo();
//Update all 4 parameters of returninfo and we are done
retInfo.maxheight = max(leftReturnInfo.maxheight, rightReturnInfo.maxheight) + 1;
//Update retInfo.heightList accordingly
retInfo.heightList = ....
retInfo.maxPathLen = max(leftReturnInfo.maxPathLen, rigthReturnInfo.maxPathLen, leftReturnInfo.maxHeight+rightReturnInfo.maxHeight+1);
//Remember from where maxPathLen came from and update accordingly
retInfo.pathList = .....
return retInfo;//We are done
}
You need a function that returns longest branch in a subtree and the longest path:
PS: I am leaving out details (Eg. Boundary conditions and so on). But this should give you an idea. This function returns two things 'branch' and 'path'. 'branch' is the longest path from this node to any of its leaves. 'path' is the longest path between any two leaves in this subtree.
def longestPath(node):
(leftBranch, leftPath) = longestPath(node.left);
(rightBranch, rightPath) = longestPath(node.right);
if len(rightBranch) > len(leftBranch):
curBranch = rightBranch+node.name
else:
curBranch = leftBranch+node.name
curPath = leftBranch + node.name + rev(rightBranch)
bestPath = curPath
if len(leftPath) > length(bestPath):
bestPath = leftPath
if len(rightPath) > length(bestPath):
bestPath = rightPath
return (curBranch, bestPath)
defintion:
node: (char content, node left , node right , node parent)
add(list , node): add node as last element in list
remove(list , index): remove and return element at index in list
length(string): length of string
insert(string , char , index): insert char at index in string
concat(string a , string OR char b): append b to a
input: node start
output: string
start
list nodes
node n
add(nodes , start)
do
n = remove(nodes , 0)
if n.parent != null
add(nodes , n.parent)
if n.left != null
add(nodes , n.left)
if n.right != null
add(nodes , n.right)
while !isEmpty(nodes)
//n now is the node with the greatest distance to start
string left = ""
string right = ""
node a = start
node b = n
while(a != b)
insert(left , a.content , length(left) - 1)
insert(right , b.content , 0)
a = a.parent
b = b.parent
string result = left
concat(result , a.content)
concat(result , right)
return result
Here is my Scala solution (Tree.scala):
/** Searches for the longest possible leaf-to-leaf path in this tree.
*
* Time - O(log^2 n)
* Space - O(log n)
*/
def diameter: List[A] = {
def build(t: Tree[A], p: List[A]): List[A] =
if (t.isEmpty) p
else if (t.left.height > t.right.height) build(t.left, t.value :: p)
else build(t.right, t.value :: p)
if (isEmpty) Nil
else {
val ld = left.diameter
val rd = right.diameter
val md = if (ld.length > rd.length) ld else rd
if (1 + left.height + right.height > md.length)
build(right, value :: build(left, Nil).reverse).reverse
else md
}
}
The idea is quite simple:
We recursively search for diameters in children (ld and rd and maximum 'md').
Check whether the longest possibe path that goes through current node is greather then diameters of its children or not (if (1 + ....)).
If its greater then we just need to build a new path with build function, which bilds a longest path from given node 't' to leaf. So, we just concatenates two resuts of this function (for left and right child) with current node.
If its not greater then the diameter is found it is md.
Longest leaf to leaf path means finding diameter of a tree. It can be done using height function.
There are many solutions available online.
Here is my Swift solution:
func diameterPath() -> [T] {
return diameterPathHelper(root).Path
}
typealias HeightAndDiameterAndPath = (Height: Int, Diameter: Int, Path: [T])
private func diameterPathHelper(node: TreeNode<T>?) -> HeightAndDiameterAndPath {
guard let node = node else {
return HeightAndDiameterAndPath(0, 0, [])
}
let left = diameterPathHelper(node.left)
let right = diameterPathHelper(node.right)
let height = max(left.Height, right.Height) + 1
if left.Height + right.Height + 1 > max(left.Diameter, right.Diameter) {
let currentDiameter = left.Height + right.Height + 1
let path = left.Path + [node.data] + right.Path
return HeightAndDiameterAndPath(height, currentDiameter, path)
} else {
if left.Diameter > right.Diameter {
return HeightAndDiameterAndPath(height, left.Diameter, left.Path)
} else {
return HeightAndDiameterAndPath(height, right.Diameter, right.Path)
}
}
}
We can use the maxdepth approach for this and initialize a variable max as 0.
public int diameterOfBinaryTree(TreeNode root) {
maxDepth(root);
return max;
}
private int maxDepth(TreeNode root) {
if (root == null) return 0;
int left = maxDepth(root.left);
int right = maxDepth(root.right);
max = Math.max(max, left + right);
return Math.max(left, right) + 1;
}
}
You have neglected one condition: What if the longest path doesn't pass through the root node?
static int findLongestPathLength(Node root){
if(root == null)
return 0;
int lh = getHeight(root.left);
int rh = getHeight(root.right);
return Math.max(1+lh+rh,
Math.max(findLongestPathLength(root.left),findLongestPathLength(root.right)));
}
static int getHeight(Node root){
if(root == null)
return 0;
return Math.max(getHeight(root.left)+1, getHeight(root.right)+1);
}
This will also make sure it find the longest path even if it doesn't pass through root.

How would you print out the data in a binary tree, level by level, starting at the top?

This is an interview question
I think of a solution.
It uses queue.
public Void BFS()
{
Queue q = new Queue();
q.Enqueue(root);
Console.WriteLine(root.Value);
while (q.count > 0)
{
Node n = q.DeQueue();
if (n.left !=null)
{
Console.Writeln(n.left);
q.EnQueue(n.left);
}
if (n.right !=null)
{
Console.Writeln(n.right);
q.EnQueue(n.right);
}
}
}
Can anything think of better solution than this, which doesn't use Queue?
Level by level traversal is known as Breadth-first traversal. Using a Queue is the proper way to do this. If you wanted to do a depth first traversal you would use a stack.
The way you have it is not quite standard though.
Here's how it should be.
public Void BFS()
{
Queue q = new Queue();
q.Enqueue(root);//You don't need to write the root here, it will be written in the loop
while (q.count > 0)
{
Node n = q.DeQueue();
Console.Writeln(n.Value); //Only write the value when you dequeue it
if (n.left !=null)
{
q.EnQueue(n.left);//enqueue the left child
}
if (n.right !=null)
{
q.EnQueue(n.right);//enque the right child
}
}
}
Edit
Here's the algorithm at work.
Say you had a tree like so:
1
/ \
2 3
/ / \
4 5 6
First, the root (1) would be enqueued. The loop is then entered.
first item in queue (1) is dequeued and printed.
1's children are enqueued from left to right, the queue now contains {2, 3}
back to start of loop
first item in queue (2) is dequeued and printed
2's children are enqueued form left to right, the queue now contains {3, 4}
back to start of loop
...
The queue will contain these values over each loop
1: {1}
2: {2, 3}
3: {3, 4}
4: {4, 5, 6}
5: {5, 6}
6: {6}
7: {}//empty, loop terminates
Output:
1
2
3
4
5
6
Since the question requires printing the tree level by level, there should be a way to determine when to print the new line character on the console. Here's my code which tries to do the same by appending NewLine node to the queue,
void PrintByLevel(Node *root)
{
Queue q;
Node *newline = new Node("\n");
Node *v;
q->enque(root);
q->enque(newline);
while(!q->empty()) {
v = q->deque();
if(v == newline) {
printf("\n");
if(!q->empty())
q->enque(newline);
}
else {
printf("%s", v->val);
if(v->Left)
q-enque(v->left);
if(v->right)
q->enque(v->right);
}
}
delete newline;
}
Let's see some Scala solutions. First, I'll define a very basic binary tree:
case class Tree[+T](value: T, left: Option[Tree[T]], right: Option[Tree[T]])
We'll use the following tree:
1
/ \
2 3
/ / \
4 5 6
You define the tree like this:
val myTree = Tree(1,
Some(Tree(2,
Some(Tree(4, None, None)),
None
)
),
Some(Tree(3,
Some(Tree(5, None, None)),
Some(Tree(6, None, None))
)
)
)
We'll define a breadthFirst function which will traverse the tree applying the desired function to each element. With this, we'll define a print function and use it like this:
def printTree(tree: Tree[Any]) =
breadthFirst(tree, (t: Tree[Any]) => println(t.value))
printTree(myTree)
Now, Scala solution, recursive, lists but no queues:
def breadthFirst[T](t: Tree[T], f: Tree[T] => Unit): Unit = {
def traverse(trees: List[Tree[T]]): Unit = trees match {
case Nil => // do nothing
case _ =>
val children = for{tree <- trees
Some(child) <- List(tree.left, tree.right)}
yield child
trees map f
traverse(children)
}
traverse(List(t))
}
Next, Scala solution, queue, no recursion:
def breadthFirst[T](t: Tree[T], f: Tree[T] => Unit): Unit = {
import scala.collection.mutable.Queue
val queue = new Queue[Option[Tree[T]]]
import queue._
enqueue(Some(t))
while(!isEmpty)
dequeue match {
case Some(tree) =>
f(tree)
enqueue(tree.left)
enqueue(tree.right)
case None =>
}
}
That recursive solution is fully functional, though I have an uneasy feeling that it can be further simplified.
The queue version is not functional, but it is highly effective. The bit about importing an object is unusual in Scala, but put to good use here.
C++:
struct node{
string key;
struct node *left, *right;
};
void printBFS(struct node *root){
std::queue<struct node *> q;
q.push(root);
while(q.size() > 0){
int levelNodes = q.size();
while(levelNodes > 0){
struct node *p = q.front();
q.pop();
cout << " " << p->key ;
if(p->left != NULL) q.push(p->left);
if(p->right != NULL) q.push(p->right);
levelNodes--;
}
cout << endl;
}
}
Input :
Balanced tree created from:
string a[] = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n"};
Output:
g
c k
a e i m
b d f h j l n
Algorithm:
Create an ArrayList of Linked List Nodes.
Do the level order traversal using queue(Breadth First Search).
For getting all the nodes at each level, before you take out a node from queue, store the size of the queue in a variable, say you call it as levelNodes.
Now while levelNodes > 0, take out the nodes and print it and add their children into the queue.
After this while loop put a line break.
P.S: I know the OP said, no queue. My answer is just to show if someone is looking for a C++ solution using queue.
public class LevelOrderTraversalQueue {
Queue<Nodes> qe = new LinkedList<Nodes>();
public void printLevelOrder(Nodes root)
{
if(root == null) return;
qe.add(root);
int count = qe.size();
while(count!=0)
{
System.out.print(qe.peek().getValue());
System.out.print(" ");
if(qe.peek().getLeft()!=null) qe.add(qe.peek().getLeft());
if(qe.peek().getRight()!=null) qe.add(qe.peek().getRight());
qe.remove(); count = count -1;
if(count == 0 )
{
System.out.println(" ");
count = qe.size();
}
}
}
}
In order to print out by level, you can store the level information with the node as a tuple to add to the queue. Then you can print a new line whenever the level is changed. Here is a Python code to do so.
from collections import deque
class BTreeNode:
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
def printLevel(self):
""" Breadth-first traversal, print out the data by level """
level = 0
lastPrintedLevel = 0
visit = deque([])
visit.append((self, level))
while len(visit) != 0:
item = visit.popleft()
if item[1] != lastPrintedLevel: #New line for a new level
lastPrintedLevel +=1
print
print item[0].data,
if item[0].left != None:
visit.append((item[0].left, item[1] + 1))
if item[0].right != None:
visit.append((item[0].right, item[1] + 1))
Try this one (Complete code) :
class HisTree
{
public static class HisNode
{
private int data;
private HisNode left;
private HisNode right;
public HisNode() {}
public HisNode(int _data , HisNode _left , HisNode _right)
{
data = _data;
right = _right;
left = _left;
}
public HisNode(int _data)
{
data = _data;
}
}
public static int height(HisNode root)
{
if (root == null)
{
return 0;
}
else
{
return 1 + Math.max(height(root.left), height(root.right));
}
}
public static void main(String[] args)
{
// 1
// / \
// / \
// 2 3
// / \ / \
// 4 5 6 7
// /
// 21
HisNode root1 = new HisNode(3 , new HisNode(6) , new HisNode(7));
HisNode root3 = new HisNode(4 , new HisNode(21) , null);
HisNode root2 = new HisNode(2 , root3 , new HisNode(5));
HisNode root = new HisNode(1 , root2 , root1);
printByLevels(root);
}
private static void printByLevels(HisNode root) {
List<HisNode> nodes = Arrays.asList(root);
printByLevels(nodes);
}
private static void printByLevels(List<HisNode> nodes)
{
if (nodes == null || (nodes != null && nodes.size() <= 0))
{
return;
}
List <HisNode> nodeList = new LinkedList<HisNode>();
for (HisNode node : nodes)
{
if (node != null)
{
System.out.print(node.data);
System.out.print(" , ");
nodeList.add(node.left);
nodeList.add(node.right);
}
}
System.out.println();
if (nodeList != null && !CheckIfNull(nodeList))
{
printByLevels(nodeList);
}
else
{
return;
}
}
private static boolean CheckIfNull(List<HisNode> list)
{
for(HisNode elem : list)
{
if (elem != null)
{
return false;
}
}
return true;
}
}
I think what you expecting is to print the nodes at each level either separated by a space or a comma and the levels be separated by a new line. This is how I would code up the algorithm. We know that when we do a breadth-first search on a graph or tree and insert the nodes in a queue, all nodes in the queue coming out will be either at the same level as the one previous or a new level which is parent level + 1 and nothing else.
So when you are at a level keep printing out the node values and as soon as you find that the level of the node increases by 1, then you insert a new line before starting to print all the nodes at that level.
This is my code which does not use much memory and only the queue is needed for everything.
Assuming the tree starts from the root.
queue = [(root, 0)] # Store the node along with its level.
prev = 0
while queue:
node, level = queue.pop(0)
if level == prev:
print(node.val, end = "")
else:
print()
print(node.val, end = "")
if node.left:
queue.append((node.left, level + 1))
if node.right:
queue.append((node.right, level + 1))
prev = level
At the end all you need is the queue for all the processing.
I tweaked the answer so that it shows the null nodes and prints it by height.
Was actually fairly decent for testing the balance of a red black tree. can
also add the color into the print line to check black height.
Queue<node> q = new Queue<node>();
int[] arr = new int[]{1,2,4,8,16,32,64,128,256};
int i =0;
int b = 0;
int keeper = 0;
public void BFS()
{
q.Enqueue(root);
while (q.Count > 0)
{
node n = q.Dequeue();
if (i == arr[b])
{
System.Diagnostics.Debug.Write("\r\n"+"("+n.id+")");
b++;
i =0 ;
}
else {
System.Diagnostics.Debug.Write("(" + n.id + ")");
}
i++;
if (n.id != -1)
{
if (n.left != null)
{
q.Enqueue(n.left);
}
else
{
node c = new node();
c.id = -1;
c.color = 'b';
q.Enqueue(c);
}
if (n.right != null)
{
q.Enqueue(n.right);
}
else
{
node c = new node();
c.id = -1;
c.color = 'b';
q.Enqueue(c);
}
}
}
i = 0;
b = 0;
System.Diagnostics.Debug.Write("\r\n");
}
Of course you don't need to use queue. This is in python.
# Function to print level order traversal of tree
def printLevelOrder(root):
h = height(root)
for i in range(1, h+1):
printGivenLevel(root, i)
# Print nodes at a given level
def printGivenLevel(root , level):
if root is None:
return
if level == 1:
print "%d" %(root.data),
elif level > 1 :
printGivenLevel(root.left , level-1)
printGivenLevel(root.right , level-1)
""" Compute the height of a tree--the number of nodes
along the longest path from the root node down to
the farthest leaf node
"""
def height(node):
if node is None:
return 0
else :
# Compute the height of each subtree
lheight = height(node.left)
rheight = height(node.right)
return max(lheight, reight)
Try with below code.
public void printLevelOrder(TreeNode root) {
if (root == null) {
return;
}
Queue<TreeNode> nodesToVisit = new LinkedList<>();
nodesToVisit.add(root);
int count = nodesToVisit.size();
while (count != 0) {
TreeNode node = nodesToVisit.remove();
System.out.print(" " + node.data);
if (node.left != null) {
nodesToVisit.add(node.left);
}
if (node.right != null) {
nodesToVisit.add(node.right);
}
count--;
if (count == 0) {
System.out.println("");
count = nodesToVisit.size();
}
}
}
here is my answer.
//for level order traversal
func forEachLevelOrder(_ visit : (TreeNode) -> Void) {
visit(self)
var queue = Queue<TreeNode>()
children.forEach {
queue.Enqueue($0)
}
while let node = queue.Dequeue() {
visit(node)
node.children.forEach { queue.Enqueue($0)}
}
}
children is an array here that stores the children of a node.

Resources