Given a binary tree where value of each internal node is 1 and leaf node is 0. Every internal
node has exactly two children. Now given level order traversal of this tree return postorder
traversal of the same tree.
This question can be easily solved if I construct a tree and then do its postorder traversal. Although it is O(n) time. But is it possible to print postOrder traversal without building up the tree.
It's definitely possible.
Considering it's a Full Binary Tree, once the number of nodes is determined, theoretically, the shape of tree is unique.
Deem the level order traversal as an array, for example, 1 2 3 4 5 6 7.
It represents such tree:
1
2 3
4 5 6 7
What you want to get is the post order traversal: 4 5 2 6 7 3 1.
The first step is calculate how deep the tree was:
depth = ceil(log(2, LevelOrderArray.length)) // =3 for this example
after that, set up a counter = 0, and extract nodes from the bottom level of the original array, one by one:
for(i=0, i<LevelOrderArray.length, i++){
postOrderArray[i] = LevelOrderArray[ 2 ^ (depth-1) +i ] //4,5,....
counter++; //1,2,.....
}
But notice that once the counter can be divided by 2, that means you need to retrieve another node from upper level:
if(counter mod 2^1 == 0)
postOrderArray[i] = LevelOrderArray[ 2 ^ (depth -2) + (++i) ] // =2 here,
//which is the node you need after 4 and 5, and get 3 after 6 and 7 at the 2nd round
Don't ++ the counter here, because the counter represents how many nodes you retrieved from the bottom level.
Every time 2^2 = 4 nodes was pop out, retrieve another node from 3rd level (counting from bottom)
if(counter mod 2^2 == 0)
postOrderArray[i] = LevelOrderArray[ 2 ^ (depth -3) + (++i) ] // =1
Every time 2^3 = 8 nodes was pop out, again, retrieve another node from 4th level
.... until the loop is finished.
It's not strict C++ code, only the concept. If you fully understand the algorithm, the value of tree nodes doesn't matter at all, even though there are all 0 and 1. The point is although you didn't build up the tree in program, but build it up in your mind instead, and convert it into algorithm.
Related
I was looking at questions on binary trees, and I came across the following:
Given the in-order traversal of a binary tree, print the pre-order traversals of all possible binary trees satisfying the given in-order traversal.
For e.g, if the in-order traversal is: {4, 5, 7}
The possible trees are:
4 4 5 7 7
\ \ / \ / /
5 7 4 7 4 5
\ / \ /
7 5 5 4
Therefore, the pre-order traversals are:
4 5 7
4 7 5
5 4 7
7 4 5
7 5 4
The solution I came up with:
Traverse the given in-order list. Upon each iteration, select an element from the list and make it the root of our tree. All elements preceding the current one will be part of the left subtree and all elements succeeding it will form the right subtree. We can then recursively do the same for the left and right subtrees.
For instance, in the above example, I begin by selecting 4 as the root of my tree. Now since there are no elements preceding 4, I cannot have a left subtree. I look at the remaining elements. They will form the right subtree. I select 5 to be the root of this subtree. For this, I am only left with one choice: to construct the right subtree of 5 from 7. That gives the first tree of the example.
Now, I keep 4 as the root, and instead of selecting 5, I select 7 as the root of the right subtree of 4. This leads me to the second tree of the example above.
That much is fine. The problem comes up with the code. I've spent quite sometime on translating the above solution to code. But I haven't been completely successful.
This is what I've tried in C++:
void solve(vector<int> inOrder, int beg, int end, string &s, bool &flag)
{
for(int i = beg; i <= end; ++i)
{
s += to_string(inOrder[i]);
flag = false;
solve(inOrder, beg, i - 1, s, flag);
solve(inOrder, i + 1, end, s, flag);
if(s.size() == inOrder.size()) {flag = true; cout << s << endl;}
if(s.size() && flag) {s.pop_back();}
}
}
I use a string to store the current permutation of elements in the pre-order traversal. Elements are appended to the string when a permutation satisfies the in-order traversal.
Naturally, elements must be subsequently removed from the string to make way for other permutations. However, I haven't been able to figure out when to remove an element. In the above code, I append an element the first time it is encountered, and I start removing elements when the string has size equal to that of the in-order list.
So, let's say I begin with 4. I append 4 to the string. I do the same for 5 and then 7. Now the string size equals the total number of elements. So I remove the last one. My string is now 45. Since there are no more possible combinations with the current string, I remove 5. I'm left with 4. Now, I can append 7 and then 5, leading to 475. This works fine in this case, but I haven't been able to make it work for other combinations. It fails when I begin by making 5 as the root, instead of 4.
So my question is, how exactly should I proceed to solve the above problem? Am I even doing it the right way? Or should I give up this approach and think of something else? If yes, what direction should I proceed in?
I'm not looking for an exact solution, only a hint as to what I'm missing or what I could do better.
So I need help coming up with an expression that will always give me the location of a child's parent node in a binary tree. Here is an example of a problem my teacher will put on our exam:
"Consider a complete binary tree with exactly 10,000 nodes, implemented with an array starting at index 0 . The array is populated in order by extracting elements from the tree one level at a time from left to right. Suppose that a node has its value stored in location 4999. Where is the value stored for this node’s parent?"
My teacher did not tell us how to solve a problem like this. She just said "Draw a binary tree and find a pattern." I did just that but i could not come up with anything! please help. thanks.
The following is entirely using integer division. I.e. fractional remainders are dropped. For any given node index N, the children of that node will always be in locations 2N+1 and 2(N+1) in the same array.
Therefore, The parent of any node N > 0 in such an array will always be at index (N-1)/2.
Parent to Child Examples:
Parent 0: children 1,2
Parent 1: children 3,4
Parent 2: children 5,6
Parent 3: children 7,8
etc...
Child to Parent Examples:
Child 8 : Parent = (8-1)/2 = 7/2 = 3
Child 7 : Parent = (7-1)/2 = 6/2 = 3
Child 6 : Parent = (6-1)/2 = 5/2 = 2
Child 5 : Parent = (5-1)/2 = 4/2 = 2
So for your problem:
(4999-1)/2 = 4998/2 = 2499
Note: remember this, since you'll be using it extensively when you start coding array-based heap-sort algorithms.
Thanks for all your help guys. And I found the answer to my question!
The general algorithm for finding the location of the parent node is:
[i + (root - 1)] / 2 where i is the location of the given node and root is the location of the root. So in the given problem above the root starts at position 0. so the equation to find the parent node of any node is [i + (0 - 1)] / 2 = (i - 1) / 2
Now let's say the root started at position 3, then the equation would be [i + (3 - 1)] / 2
= (i + 2) / 2!!!! This is the algorithm I needed. Most of you helped me solve the one problem i provided but i actually needed the general solution for a binary tree whose root can start at any postions; not just at zero
It seems this is how the array elements map back to tree based on array indices
0
1 2
3 4 5 6
If so, then the parent of index n is at floor( (n - 1) / 2 ) (for n != 0)
If you do the log2 of the number requested (4999) and take the integer part it will give you the closest power of two to the number (12). It is 2^12 = 4096.
The parent of the nodes between 4096 and 2^13 - 1, are the ones between 2^11 and 2^12 - 1. And for each pair of nodes in the first range you have its parent in the second. So you can map them taking the integer part of the half of the difference (4999 - 4096) and adding it to the parent range start (2048).
So you will have floor of 903 / 2, and add it to 2048, getting 2499.
Note that I didn't make a precise calculation, take the strategy of the answer not the results.
You can put this algorithm in a mathematical expression, with a little work.
Hope it helps!
The parent node is at n/2 if n is even.
It is at (n-1)/2 if n is odd.
So you can remember it as math.ceil((n-1)/2)
I am having trouble understanding this maxDepth code. Any help would be appreciated. Here is the snippet example I followed.
int maxDepth(Node *&temp)
{
if(temp == NULL)
return 0;
else
{
int lchild = maxDepth(temp->left);
int rchild = maxDepth(temp->right);
if(lchild <= rchild)
return rchild+1;
else
return lchild+1;
}
}
Basically, what I understand is that the function recursively calls itself (for each left and right cases) until it reaches the last node. once it does, it returns 0 then it does 0+1. then the previous node is 1+1. then the next one is 2+1. if there is a bst with 3 left childs, int lchild will return 3. and the extra + 1 is the root. So my question is, where do all these +1 come from. it returns 0 at the last node but why does it return 0+1 etc. when it goes up the left/right child nodes? I don't understand why. I know it does it, but why?
Consider this part (of a bigger tree):
A
\
B
Now we want to calculate the depth of this treepart, so we pass pointer to A as its param.
Obviously pointer to A is not NULL, so the code has to:
call maxDepth for each of A's children (left and right branches). A->right is B, but A->left is obviously NULL (as A has no left branch)
compare these, choose the greatest value
return this chosen value + 1 (as A itself takes a level, doesn't it?)
Now we're going to look at how maxDepth(NULL) and maxDepth(B) are calculated.
The former is quite easy: the first check will make maxDepth return 0. If the other child were NULL too, both depths would be equal (0), and we have to return 0 + 1 for A itself.
But B is not empty; it has no branches, though, so (as we noticed) its depth is 1 (greatest of 0 for NULLs at both parts + 1 for B itself).
Now let's get back to A. maxDepth of its left branch (NULL) is 0, maxDepth of its right branch is 1. Maximum of these is 1, and we have to add 1 for A itself - so it's 2.
The point is the same steps are to be done when A is just a part of the bigger tree; the result of this calculation (2) will be used in the higher levels of maxDepth calls.
Depth is being calculated using the previous node + 1
All the ones come from this part of the code:
if(lchild <= rchild)
return rchild + 1;
else
return lchild + 1;
You add yourself +1 to the results obtained in the leaves of the tree. These ones keep adding up until you exit all the recursive calls of the function and get to the root node.
Remember in binary trees a node has at most 2 children (left and right)
It is a recursive algorithm, so it calls itself over and over.
If the temp (the node being looked at) is null, it returns 0, as this node is nothing and should not count. that is the base case.
If the node being looked at is not null, it may have children. so it gets the max depth of the left sub tree (and adds 1, for the level of the current node) and the right subtree (and adds 1 for the level of the current node). it then compares the two and returns the greater of the two.
It dives down into the two subtrees (temp->left and temp->right) and repeats the operation until it reaches nodes without children. at that point it will call maxDepth on left and right, which will be null and return 0, and then start returning back up the chain of calls.
So if you you have a chain of three nodes (say, root-left1-left2) it will get down to left2 and call maxDepth(left) and maxDepth(right). each of those return 0 (they are null). then it is back at left2. it compares, both are 0, so the greater of the two is of course 0. it returns 0+1. then we are at left1 - repeats, finds that 1 is the greater of its left n right (perhaps they are the same or it has no right child) so it returns 1+1. now we are at root, same thing, it returns 2+1 = 3, which is the depth.
Because the depth is calculated with previous node+1
To find Maximum depth in binary tree keep going left and Traveres the tree, basically perform a DFS
or
We can find the depth of the binary search tree in three different recursive ways
– using instance variables to record current depth and total depth at every level
– without using instance variables in top-bottom approach
– without using instance variables in bottom-up approach
The code snippet can be reduced to just:
int maxDepth(Node *root){
if(root){ return 1 + max( maxDepth(root->left), maxDepth(root->right)); }
return 0;
}
A good way of looking at this code is from the top down:
What would happen if the BST had no nodes? We would have root = NULL and the function would immediately return an expected depth of 0.
Now suppose the tree was populated with a number of nodes. Starting at the top, the if condition would be true for the root node. We then ask, what is the max depth of the LEFT SUB TREE and the RIGHT SUB TREE by passing the root of those sub trees to maxDepth. Both the LST and the RST of the root are one level deeper than the root, so we must add one to get the depth of the tree at root of the tree passed to the function.
i think this is the right answer
int maxDepth(Node *root){
if(root){ return 1 + max( maxDepth(root->left), maxDepth(root->right)); }
return -1;
}
Given a tree (binary) structure, with depth N. Is it possible to compute some lookup index for mapping leaf nodes.
Each node knows its parent, and its childs(left and right) if its not a leaf.
My Idea was something like saying rootnode is index 0, then left:1,left:left:2, left:left:left:3, left:left:right:4, left:right:left:5,left:right:right:6,right:7,right:left:8 e.g.
So given a leaf node, how can i compute the index smartest.
Other solutions are accepted also, if its smarter to give the leafs indexes from 0,1...L, where L is the number of leafs.
If you wish to represent a tree in an array, the simplest is to take the layers of tree one at a time.
0
/ \
/ \
1 2 [0, 1, 2, 3, 4, 5, 6]
/ \ / \
3 4 5 6
This way, finding the parent is simply: (index-1)/2. And finding the two children is just 2*index and 2*index + 1.
In my Tree structure (Quadtree and Octree) I am using a binary representation of the indexes of each node. e.g. 32 bit (for max 32 level) for each dimension.
So I can compute the complete index (or path) of a leaf by the formula
path.x = (unsigned int)(leaf.position.x * pow(2,32));
leaf.position.x musst be in a range from 0...1
The only constraint (I think) for this method is that the data you are storing musst be in a specific range, so that you can devide it by your area size.
If this is possible for your usecase read more at
Simple and Efficient Traversal Methods for
Quadtrees and Octrees
Im trying to build a kd-tree for searching through a set of points, but am getting confused about the use of 'median' in the wikipedia article. For ease of use, the wikipedia article states the pseudo-code of kd-tree construction as:
function kdtree (list of points pointList, int depth)
{
if pointList is empty
return nil;
else
{
// Select axis based on depth so that axis cycles through all valid values
var int axis := depth mod k;
// Sort point list and choose median as pivot element
select median by axis from pointList;
// Create node and construct subtrees
var tree_node node;
node.location := median;
node.leftChild := kdtree(points in pointList before median, depth+1);
node.rightChild := kdtree(points in pointList after median, depth+1);
return node;
}
}
I'm getting confused about the "select median..." line, simply because I'm not quite sure what is the 'right' way to apply a median here.
As far as I know, the median of an odd-sized (sorted) list of numbers is the middle element (aka, for a list of 5 things, element number 3, or index 2 in a standard zero-based array), and the median of an even-sized array is the sum of the two 'middle' elements divided by two (aka, for a list of 6 things, the median is the sum of elements 3 and 4 - or 2 and 3, if zero-indexed - divided by 2.).
However, surely that definition does not work here as we are working with a distinct set of points? How then does one choose the correct median for an even-sized list of numbers, especially for a length 2 list?
I appreciate any and all help, thanks!
-Stephen
It appears to me that you understand the meaning of median, but you are confused with something else. What do you mean be distinct set of points?
The code presented by Wikipedia is a recursive function. You have a set of points, so you create a root node and choose a median of the set. Then you call the function recursively - for the left subtree you pass in a parameter with all the points smaller than the split-value (the median) of the original list, for the right subtree you pass in the equal and larger ones. Then for each subtree a node is created where the same thing happens. It goes like this:
First step (root node):
Original set: 1 2 3 4 5 6 7 8 9 10
Split value (median): 5.5
Second step - left subtree:
Set: 1 2 3 4 5
Split value (median): 3
Second step - right subtree:
Set: 6 7 8 9 10
Split value (median): 8
Third step - left subtree of left subtree:
Set: 1 2
Split value (median): 1.5
Third step - right subtree of left subtree:
Set: 3 4 5
Split value (median): 4
Etc.
So the median is chosen for each node in the tree based on the set of numbers (points, data) which go into that subtree. Hope this helps.
You have to choose an axis with as many element on one side than the other. If the number of points is odd or the points are positioned in such a way that it isn't possible, just choose an axis to give an as even repartition as possible.