I am working on LeetCode problem 110. Balanced Binary Tree:
Given a binary tree, determine if it is height-balanced.
For this problem, a height-balanced binary tree is defined as:
a binary tree in which the left and right subtrees of every node differ in height by no more than 1.
I've seen solutions for this question, including this one:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
int max(int a, int b){
return (a > b) ? a:b;
}
int height(struct TreeNode* root){
if(root == NULL) return 0;
return 1 + max(height(root->left),height(root->right));
}
bool isBalanced(struct TreeNode* root){
if(root == NULL) return 1;
int left = height(root->left);
int right = height(root->right);
return abs(left - right) <= 1 && isBalanced(root->left) && isBalanced(root->right);
}
My question is: why should this code be added?
isBalanced(root->left) && isBalanced(root->right);
It seems to be working fine when I delete this from the code. However, when the test case is [1,2,2,3,null,null,3,4,null,null,4], the code will return true, while the expected answer is false.
I am full of doubts about this test, because both ends of the test tree are the same depth, so abs(left-right) should be 0, and 0<=1, so shouldn't the answer for this test be true!?
the test case is [1,2,2,3,null,null,3,4,null,null,4],
So let's visualise that tree:
1
/ \
2 2
/ \
3 3
/ \
4 4
the code will return true, while the expected answer is false,
The expected answer is false: the above tree is not a balanced tree.
I am full of doubts about this test, because both ends of the test tree are the same depth, so abs(left-right) should be 0, and 0<=1, so shouldn't the answer for this test be true!?
You are right that abs(left-right) is 0 and that's within the bounds [-1,1], but in a balanced tree, this condition must be true in every node. So your code must also check that abs(left-right) is within the limits for other nodes. And then you can see that the first node with value 2, has a left-subtree that is 2 levels higher than its right-subtree (which is empty). So there we have a violation of the rule, and the correct answer is false.
This explains why you really need those two recursive calls to isBalanced.
a binary tree in which the left and right subtrees of every node differ in height by no more than 1.
Here you have already mentioned why your implementation is throwing up an error. Your code only checks the height balancing at the root node(topmost node).
The difference of heights in every node must be [-1,0,1] in a balanced tree. An easier visualization will be considering each node has a small tree itself.
Let this be the testcase [1,2,2,3,null,null,3,4,null,null,4].
1
/ \
2 2
/ \
3 3
/ \
4 4
If you only check the root node, the abs(left-right) is 0. But consider the left node 2. And visualize it a smaller tree or a subtree.
2
/
3
/
4
If this is a tree on its own then it's not balanced since abs(left-right) == 2.Since we have found a node that is not balanced we return false.
Thus to solve this problem, we have to consider each node as a separate tree itself. Such problems require recursive algorithms that checks the isBalanced property from the highest to the lowest nodes by calling their child nodes recursively.
Related
Consider a rooted n node binary tree represented using pointers. The best upper bound on the time required to determine the number of subtrees having exactly 4 nodes is O(n^a Log^b(n)). Then the value of a+10b is __________.
My attempt:
Somewhere algorithm is given as following:
int print4Subtree(struct Node *root) {
if (root == NULL)
return 0;
int l = print4Subtree(root->left);
int r = print4Subtree(root->right);
if ((l + r + 1) == 4)
printf("%d ", root->data);
return (l + r + 1); }
This algorithm runs O(n) time , so answer will be 1 .
Is it correct or any other better algorithm exist?
Can you explain in formal/alternative way, please.
In computer science, a subtree usually means that there are no further nodes connected below it, but in graph theory, the term subtree does not imply this -- it just means a subgraph (subset of nodes and edges) that is also a tree. So e.g. if you have a 10-node path with the root at one end, there are 7 subtrees according to the graph theory definition, instead of 1. There are usually (many) more subtrees according to the graph theory definition... This could be where the log factor comes from in the question.
On the other hand, there are just a constant number of 4-node rooted binary trees -- I count 14 in total (8 height-3 trees, 4 height-2 trees in which the root has 2 children, and 2 height-2 trees in which the root has 1 child). So even with the new, broader definition, it would be possible to check each node in the tree to see which of the 14 possible 4-node rooted binary trees are rooted at this node, and add this count to a grand total, all in O(n) time.
How to convert a tree to its mirror tree. For eg.
1 1
/ \ / \
2 3 to 3 2
/ \
4 4
Perform post order traversal.
void mirror(struct node* node)
{
if (node!=NULL)
{
struct node* temp;
/* do the subtrees */
mirror(node->left);
mirror(node->right);
/* swap the pointers in this node */
temp = node->left;
node->left = node->right;
node->right = temp;
}
}
Solution uses recursion to convert a tree to its mirror tree.
If root of both trees are null, then they are same. Return true.
If roots of both the trees are not null, check if the data in the two nodes is same and recursively check if left and right subtrees are identical.
If the roots of only one of the trees is null, then the trees are not identical, so return false.
Source: http://www.ideserve.co.in/learn/mirror-a-tree
I am currently learning about the BST and writing different functions such as insert search. I came across an interesting programming interview question and it asked to write a function that will check if the bst is complete.
So my understanding is that a BST is complete if all the leaves terminate at the same level.
My possible approach for this solution
I figured that height of the right and left nodes should be the same if the leaves under them terminate at the same level. so can I do a simple check to see if the height of a right sub tree is the same as the left sub-tree and if it is then that should indicate to me that the BST tree is complete. Can anyone confirm if my approach is right or suggest other possible approaches? i am not looking for code just want to work on my understanding and approach.
Your recursive approach is almost correct. What you want to ask about a given node are the following questions:
Is the left child the root of a complete BST, and if so, what is its height?
Is the right child the root of a complete BST, and if so, is its height the same as that of the left child?
If the answer to both is yes, you have a complete BST.
A different way to solve this problem is to answer the following three questions about the tree.
Is it a BST?
How many nodes are in it?
What is its height?
If the tree is a BST of height h with 2**h - 1 nodes, you have a complete BST. Each of the three questions can be answered with a recursive tree traversal.
Your approach won't work because the tree might be equal on left and right and not the same for all leaves like:
5
/\
3 6
/ \
1 7
This tree has equal left and right but 6 doesn't have left child and 3 doesn't have right child.
And the definition of complete tree is
A complete binary tree is a binary tree in which every level, except possibly the last, is completely filled, and all nodes are as far left as possible
Number of nodes = 2^n-1 is not going to solve it as well because it might contain that number but not balanced.
The correct approach would be to
traverse the tree using something like post-order traversal and when you reach the first leaf, you set the max_depth
during the traversal if you reach a leaf node, it must be at max_depth or depth can decrease to be max_depth -1 but the depth can't increase again after that.
and that is to handle a case like this (which is a complete BST tree)
4
/\
2 6
/ \ /\
1 3 5
Your basic idea I think is correct. You just recursively check whether the left tree is of the same height as the right tree.
The code looks like
int isComplete(Tree *t){
if(t->left==NULL && t->right==NULL)
return 0;
else if(t->left!=NULL && t->right != NULL){
int leftheight = isComplete(t->left);
int rightheight = isComplete(t->right);
if(leftheight == rightheight && leftheight != -1)
return leftheight+1;
}
return -1;
}
-1 indicates not complete. A non-negative return indicates the height of the tree.
Tried exploring a lot over the net, but could get any help,
Everywhere its like adding a node to the Binary Search tree.
Question: Requesting for algorithm and code snippet for adding a node to the Binary tree. ( or point me to correct URL )
Assumption:
As per my understanding, Binary Tree and Binary Search Tree is different? Correct me if I am wrong.
( request: if you are writing your code snippet please use proper variable name, that helps in understanding )
Eg: Binary Tree
5 7 3 x1 x2 x3
5
7 3
x1 x2 x3
Binary Search Tree 5 7 3 2 4 6
5
3 7
2 4 6
insert(int key, struct node **root)
{
if( NULL == *root )`
{
*root = (struct node*) malloc( sizeof( struct node ) );`
(*root)->data = key;
(*root)->left = NULL;
(*root)->right = NULL;
}
else if(key < (*root)->data)
{
insert( key, &(*root)->left );
}
else if(key > (*root)->data)
{
insert( key, &(*root)->right );
}
}
The difference between a Binary Tree and a Binary Search Tree is that though they both have restrictions that each node can have at most 2 child nodes, a Binary Search Tree (BST) also must have its left child be of equal or lesser value and the its right child must be of greater or equal value. This is why it is called a "Search" tree because everything is ordered numerically and it has an O(logn) run time for searching.
Because there isn't the requirement of being a BST, a Binary Tree can be stored in a vector (array). As you insert into the vector you build the Binary Tree in level-order fashion. The code is below:
// typedef the node struct to NODE
// nodeVector similar to STL's vector class
insert(int key, NODE** nodeVector)
{
NODE *newNode = (NODE*) malloc( sizeof( NODE ) );
newNode->data = key;
newNode->left = NULL;
newNode->right = NULL;
// add newNode to end of vector
int size = nodeVector->size();
nodeVector->push_back(newNode);
// if newNode is not root node
if(nodeVector->size() > 1)
{
// set parent's child values
Node* parent = (size/2)-1; // take advantage of integer division instead of using floor()
if (parent->left == NULL)
{
parent->left = newNode;
}
else
{
parent->right = newNode;
}
}
}
A Queue data structure can be used for inserting element in to a Binary Tree, since in Binary Tree the order of nodes is not maintained so we will insert the node as soon as we find any null.
Using Queue we will be traversing the Binary Tree in Level Order Traversal.
struct Treenode* temp;
Q = CreateQueue();
EnQueue(Q,root);
while(!IsEmptyQueue(Q))
{
temp = DeQueue(Q);
if(temp->left)
EnQueue(Q,temp->left);
else
{
temp->left=newNode;
DeleteQueue(Q);
return;
}
if(temp->right)
EnQueue(Q,temp->right);
else
{
temp->right=newNode;
DeleteQueue(Q);
return;
}
}
Since, I cannot comment I am writing this.
The above answer for binary tree insert function is wrong.
Suppose for 0, 1, 2 , 3, 4 , 5 passed in sequence to insert function,
its generating tree like
0
/
1
\
2
/
3
\
4
/
5`<br/>
of which inorder traversal will be 1 3 5 4 2 0
while answer should be
0
/ \
1 2
/ \ /
3 4 5
of which inorder traversal will be 3 1 4 0 5 2.
Since I also face the same problem, I came up with following solution over the net :-
You can use a queue to store the current node where we want to place the new node as we do in level order traversal and then we insert the nodes level by level.
Following link might help you :-
http://www.geeksforgeeks.org/linked-complete-binary-tree-its-creation/
I am posting this as answer because I dont have the necessary reputation to post a comment. Except for bagelboy all others have misunderstood the tree as either Binary Search Tree or Complete Binary Tree. The question is simple Binary Tree and Bagelboy's answer looks correct.
I need to define a main function that reads integers and prints them back in ascending order.
For example, if the input contains
12
4
19
6
the program should output
4
6
12
19
I need to use trees to do this however. I'm given the use of two functions insertavl, and deleteavlat my disposal. Their defintions are like so... http://ideone.com/8dwlU basically when deleteavl is called it deletes the node, and rebalances the tree accordingly
... If interested thier structures are in: http://ideone.com/QjlGe.
I've gotten this so far:
int main (void) {
int number;
struct node *t = NULL;
while (1 == scanf("%d",&number)) {
t = insertavl(t, number);
}
while (t != NULL){
printf("%d\n",t->data);
t = deleteavl(t, t->data);
}
}
But this doesn't print them in ascending order. Any suggestions would be helpful? thanks in advance!
Hint: in-order traversal on a BST is iterating the elements in ascending order.
Since an AVL Tree is a specific implementation of a BST, it also applies here.
EDIT: Explanation - why is this property of in-order traversal on a BST correct?
In in-order trvaersal, you access [print] each node after you accessed all the nodes in the left subtree. Since in a BST the root is bigger then all the nodes in the left subtree, it is what we wanted.
Also, in in-order traversal, you access each node before accessing all elements in the right sub-tree, and again, since it is a BST - this is exactly what we want.
(*)Note: This is not a formal proof, just an intuitive explanation why it is true.