I have a binary tree with nodes like this:
struct node
{
int info;
node *left = NULL;
node *right = NULL;
node();
node(int data, node* ln = 0, node* rn = 0): info(data), left(ln), right(rn) {}
};
bool addItemToTree(struct node* node, int item, bool isRoot) {
if (!node)
return false;
if (isRoot) {
node->info = item;
return true;
}
if (!node->left) {
node->left = new struct node(item);
}
else if (!node->right) {
node->right = new struct node(item);
}
else {
if (node->left->left && node->left->right && (!node->right->left || !node->right->right)) {
return addItemToTree(node->right, item, false);
}
else {
return addItemToTree(node->left, item, false);
}
}
return true;
}
int main()
{
node* root = createRoot();
for (int i = 1; i <= 13; i++) {
if (i == 1) {
addItemToTree(root, i, true);
}
else {
addItemToTree(root, i, false);
}
}
}
For some reason, my insert function (adds element to tree) stops working after 10 iterations, meaning it adds elements into an incorrect node (doesn't follow binary tree pattern). Anyone know why it breaks? Thanks.
I assume it's actually after 11 iterations, not 10.
That's because after 11 iterations your tree looks like this:
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ / \
8 9 10 11
Now you want to add 12 under 6, for that your addItemToTree, when looking at 1, needs to go to the right. But it only goes to the right if the right child has no children of its own. In this case the right child of 1 is 3, and it has children of its own, so your method will go to the left, which is wrong.
To fix it, you will need to maintain some auxiliary information about the nodes that would let you decide when to go to the left and when to the right. Some options:
Store the total number of nodes in a subtree. If the left subtree has number of children that is 1 less that some power of two, and the right child has less than that, go to the right (try to prove why that works).
Store whether a subtree has openings at the current depth. You go to the left child if either left->hasOpenings or if !left->hasOpenings && !right->hasOpenings (the latter means that the tree is full at the current depth, and needs to be extended). You set hasOpenings for a parent of a node whenever you recurse to a left child of the node.
In your addItemToTree maintain the current depth (the depth of the root being 0). Let leftmostOne be the index of the leftmost 1 in the binary representation of item. Go to the left if item & (1 << (leftmostOne - depth - 1)) == 0. E.g. when you add 9, the leftmostOne is 3. Then you will do three iterations, and make the following decisions:
At node 1, depth 0, 9 & (1 << (3 - 0 - 1)) = 0, go left
At node 2, depth 1, 9 & (1 << (3 - 1 - 1)) = 0, go left
At node 3, depth 2, 9 & (1 << (3 - 2 - 1)) = 1, go right
Which is exactly what you want.
Try to prove why this works for the general case.
Related
I am working on the GeeksForGeeks ZigZag Tree Traversal problem:
Given a Binary Tree. Find the Zig-Zag Level Order Traversal of the Binary Tree.
Example 1:
Input:
3
/ \
2 1
Output:
3 1 2
Example 2:
Input:
7
/ \
9 7
/ \ /
8 8 6
/ \
10 9
Output:
7 7 9 8 8 6 9 10
I am getting a Time Limit Exceeded error.
My approach is to push a NULL for each different level, and at every NULL I am changing the direction:
vector<int> ans;
queue<Node*> q;
q.push(root);
q.push(NULL);
int k = 1;
while (q.size() > 0)
{
Node * top = q.front();
q.pop();
if (!top)
{
k = 1 - k;
q.push(NULL);
continue;
}
ans.push_back(top->data);
if (k)
{
if (top->right)
q.push(top->right);
if (top->left)
q.push(top->left);
}
else
{
if (top->left)
q.push(top->left);
if (top->right)
q.push(top->right);
}
}
Why is this code not finishing in time?
The issue that causes the time out is related to the NULL you keep on the queue. That means the queue will never get empty. If you pop a NULL and the queue becomes empty, you still push a new NULL unto it so your loop never ends.
You could fix this by changing the while condition to q.size()>1, but then still there is a flaw in the algorithm:
When visiting the nodes in a level from left to right, you correctly put the right child first in the queue, and then the left child, but this only reverses the direct children. The cousins are still relating to eachother in the left-to-right order, which is wrong.
I would suggest to use two vectors instead of one queue, and let those vectors alternate.
Here is how your code would need to be adapted:
vector <int> zigZagTraversal(Node* root)
{
vector<int> ans;
vector<Node*> parents;
vector<Node*> children;
children.push_back(root);
int k = 0;
while (children.size() > 0)
{
k = 1 - k;
parents = children;
children.clear();
while (parents.size() > 0)
{
Node * top = parents.back();
parents.pop_back();
ans.push_back(top->data);
if (top->right && k == 0)
children.push_back(top->right);
if (top->left)
children.push_back(top->left);
if (top->right && k == 1)
children.push_back(top->right);
}
}
return ans;
}
#trincot
thankyou for your help
I got it where I am making mistake.
I should check the size of queue before pushing NULL
Because, at time of last NULL (what the code is doing poping NULL , check it ooh it is NULL then again push a NULL and continue doing it)
so, I have to check the size of queue at the time of pushing NULL if it is zero
have to break the loop
I am trying to attempt zig zag traversal of binary tree. But I am stuck at one type of test cases, i.e., when the tree is not balanced. If I give my input as
3
3 9 20 null null 15 7
for a binary tree which looks like this:
3
/ \
9 20
/ \
15 7
I get output:
3
20 9
0
If my input was 3 9 20 1 null 15 7, my output is:
3
20 9
1 0
Below is my code.
struct node
{
int data;
node* left;
node* right;
};
void order (node* root, map <int, vector <int> >& ans, int level, int k) {
if (root == NULL) {
return;
}
if (k==0) {
if (root->left != NULL) {
ans[level+1].push_back(root->left->data);
order (root->left, ans, level+1, 1);
}
if (root->right != NULL) {
ans[level+1].push_back(root->right->data);
order (root->right, ans, level+1, 1);
}
}
else if (k==1) {
order (root->left, ans, level+1, 0);
order (root->right, ans, level+1, 0);
if (root->right != NULL)
ans[level+1].push_back(root->right->data);
if (root->left != NULL)
ans[level+1].push_back(root->left->data);
}
}
vector<vector<int> > zigzag(node* root){
map <int, vector <int> > ans;
vector <vector <int> > zig;
ans[0].push_back(root->data);
order(root, ans, 1, 1);
for (auto it = ans.begin(); it != ans.end(); it++ ) { //converting map into vector
zig.push_back(it->second);
}
return zig;
}
From what I understand, if the input is null my code should return nothing and continue execution of further nodes. I can't figure out my mistake. Can anybody help me?
TIA!
Your code actually appears to work with your provided test case. I suspect your problem there is with input/output. However the solution itself is unfortunately not. Consider the following test case:
1
/ \
5 2
/ \
6 3
/ \
7 4
Your solution will output: [[1], [5, 2], [6, 3], [7, 4]]
Let's call each vector in your zigzag vector a level.
First you add the 1 (the root) to your first level.
k==1 level==1 Then you recurse left.
k==0 level==2 You add 6 correctly to level 2. And recurse left again.
k==1 level==3 Can't recurse left or right. Add 7 incorrectly to level 3. Return
k==0 level==2 Can't recurse right. Return.
k==1 level==1 Add 5 incorrectly to level 1. Recurse right.
etc.
I think this approach is going to be difficult to get to the correct solution. Primarily because of it's DFS nature. A BFS solution could be the right path. It is naturally suited to these level-by-level styled problems.
For level order traversal you can use the stack data structure for traversing the each level in zig zag fashion.
vector<vector<int> > Solution::zigzagLevelOrder(TreeNode* root) {
stack<TreeNode*> s1, s2;
s1.push(root);
vector< vector< int> > ans;
int check = 1;
while(!s1.empty() or !s2.empty()){
vector<int> current;
if(check){
while(!s1.empty()){
root = s1.top();
s1.pop();
current.push_back(root->val);
if(root->left)
s2.push(root->left);
if(root->right)
s2.push(root->right);
}
check = 1 - check;
}
else{
while(!s2.empty()){
root = s2.top();
s2.pop();
current.push_back(root->val);
if(root->right)
s1.push(root->right);
if(root->left)
s1.push(root->left);
}
check = 1 - check;
}
ans.push_back(current);
}
return ans;
}
Maintain the first stack for odd level and second stack for even level. While traversing the odd level push left child then right, and while traversing even level traverse right child then left.
Two trees can be called isomorphic if they have similar structure and the only difference amongst them can be is, that their child nodes may or may not be swapped. For example:
4 4
/ \ / \
2 6 and 6 2
/ \ / \ / \ / \
1 3 5 7 1 3 7 5
The following code is supposed to be correct implementation which I found in the web, but for some reason it is not working for the above trees. What I am doing wrong?
#include <iostream>
using namespace std;
class Node{
public:
Node * left;
Node * right;
int val;
Node(int v){
left = NULL;
right = NULL;
val = v;
}
};
bool isIsomorphic(Node* n1, Node *n2)
{
// Both roots are NULL, trees isomorphic by definition
if (n1 == NULL && n2 == NULL)
return true;
// Exactly one of the n1 and n2 is NULL, trees not isomorphic
if (n1 == NULL || n2 == NULL)
return false;
if (n1->val != n2->val)
return false;
// There are two possible cases for n1 and n2 to be isomorphic
// Case 1: The subtrees rooted at these nodes have NOT been "Flipped".
// Both of these subtrees have to be isomorphic, hence the &&
// Case 2: The subtrees rooted at these nodes have been "Flipped"
return
(isIsomorphic(n1->left,n2->left) && isIsomorphic(n1->right,n2->right))||
(isIsomorphic(n1->left,n2->right) && isIsomorphic(n1->right,n2->left));
}
int main()
{
Node * na_4 = new Node(4);
Node * na_2 = new Node(2);
Node * na_6 = new Node(6);
Node * na_1 = new Node(1);
Node * na_3 = new Node(3);
Node * na_5 = new Node(5);
Node * na_7 = new Node(7);
na_4->left = na_2;
na_4->right = na_6;
na_2->left = na_1;
na_2->right = na_3;
na_6->left = na_5;
na_6->right = na_7;
Node * nb_4 = new Node(4);
Node * nb_6 = new Node(6);
Node * nb_2 = new Node(2);
Node * nb_1 = new Node(1);
Node * nb_3 = new Node(3);
Node * nb_7 = new Node(7);
Node * nb_5 = new Node(5);
nb_4->left = nb_6;
nb_4->right = nb_2;
nb_6->left = nb_1;
nb_6->right = nb_3;
nb_2->left = nb_7;
nb_2->right = nb_5;
if(isIsomorphic(na_4, nb_4)){
cout << "Yes they are isomorphic" << endl;
}
else
{
cout << "No there are not isomorphic" << endl;
}
return 0;
}
It outputs that they are not isomorphic.
Those trees aren't isomorphic according to the definition you provided. A similar definition that's specific to binary trees also appears here:
Two trees are called isomorphic if one of them can be obtained from other by a series of flips, i.e. by swapping left and right children of a number of nodes. Any number of nodes at any level can have their children swapped. Two empty trees are isomorphic.
The problem is that in the one tree, 2 has children 1 and 3, but in the other tree, 2 has children 7 and 5.
By "swapping" two children, you actually need to swap their entire subtrees, not just the individual nodes and leaving all others where they are.
These two, for example, would be isomorphic:
4
/ \
2 6
/ \ / \
1 3 5 7
4
/ \
6 2
/ \ / \
7 5 1 3
Note: Some definitions of isomorphism ignore vertex labels (for more general graph isomorphism at least, in principle the same idea would apply to trees as well). Under those definitions, the trees given in the question would be isomorphic. I believe the definition given above would still apply if you ignore vertex labels. For graph isomorphism (as opposed to tree isomorphism, which takes the root into account), this would not work as general graphs have no concept of a root (trees produced by the above technique would still be graph isomorphic, but not all graphs isomorphisms can be produced using this technique).
These given trees are not isomorphic. Two trees are called isomorphic if and only if one of them can be obtained from other by a series of flips, i.e. by swapping left and right children of a number of nodes. Also, any number of nodes at any level can have their children swapped.
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
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;