If I delete node x and then node y or delete y and the x, after this deleted I will stay with the same binary search tree?
I tried a few examples and I think that's true.
But how can i prove this?
It's false. Consider the tree
4
/ \
1 5
\
2
\
3 ,
from which 4 and 5 are deleted in some order. If the order is 5 then 4, the result is
1
\
2
\
3 .
If the order is 4 then 5, the result could be
3
/
1
\
2 ,
assuming that, when we would delete a node with two children, we instead replace its value by that of its in-order predecessor and delete the predecessor. (I'm assuming also the standard deletion procedure for zero- and one-child nodes.)
Although I found this example by hand, I often turn to computer assistance.
Related
Given a tree, find the common subtrees and replace the common subtrees and compact the tree.
e.g.
1
/ \
2 3
/ | /\
4 5 4 5
should be converted to
1
/ \
2 3
/ | /\
4 5 | |
^ ^ | |
|__|___| |
|_____|
this was asked in my interview. The approach i shared was not optimal O(n^2), i would be grateful if someone could help in solutioning or redirect me to a similar problem. I couldn't find any. Thenks!
edit- more complex eg:
1
/ \
2 3
/ | /\
4 5 2 7
/\
4 5
whole subtree rooted at 2 should be replaced.
1
/ \
2 <--3
/ | \
4 5 7
You can do this in a single DFS traversal using a hash map from (value, left_pointer, right_pointer) -> node to collapse repeated occurrences of the subtree.
As you leave each node in your DFS, you just look it up in the map. If a matching node already exists, then replace it with the pre-existing one. Otherwise, add it to the map.
This takes O(n) time, because you are comparing the actual pointers to the left + right subtrees, instead of traversing the trees to compare them. The pointer comparison gives the same result, because the left and right subtrees have already been canonicalized.
Firstly, we need to store the node values that appear in a hash table. If the tree already exists, we can iterate the tree and if a node value is already in the set of nodes and delete the branches of that node. Otherwise, store the values in a hash map and each time, when a new node is made, check if the value appears in the map.
The question may look very simple, and probably the answer is too, but I always get confused in the tree questions.
Ok so I want to make a tree something like:
3 level 0
/ \
4 5 level 1 ..
/ \ / \
6 7 8
/ \ / \ / \
9 10 11 12
What are such trees called? Sorry, I'm a beginner..
Function can pass an array[] of ints, or function can take input till N = 3 (denoting level 3 with 10 nodes). Also can you give solution in C/C++/Java.
Given your requirements are only for traversal, I would simply implement this using an array a, containing each level as a contiguous sub-array. Level i then occurs in entries L(i-1) up to but not including L(i), where L(n) = n*(n+1)/2. In particular, the jth value on the ith level is in a[L(i-1)+j].
As long as you always keep track of i and j, you can now easily navigate through your pyramid.
For example, we are provided with only post order traversal array or only pre order traversal array. Can we reconstruct the binary tree back? If we know that the binary tree is full. Moreover, if it is not, is it possible to construct the full binary if know both preorder and post order at the same time?
No, you can't from one list alone.
think of the postorder list: 4 5 2 3 1
1 1
/ \ / \
2 3 4 3
/ \ / \
4 5 5 2
both trees are possible, but we don't know which one generated the list
Assuming every element in the tree is unique, we know that preorder is build like that:
[Node][ LeftTree ][ RightTree ]
and postorder like this:
[ LeftTree ][ RightTree ][Node]
if we have two lists, preorder 1 2 4 5 3 and postorder 4 5 2 3 1, we know that 1 is the root of the tree, because it is the first number of the preorder list (and the last number of the postorder list). Furthermore we know that 2 must be the root of the left tree and 3 the root of the right tree, because they are the first numbers after the root node which are roots of the left or right tree. With this in mind we can split the lists into this:
[Root in preorder] [ LeftTree ] [RightTree] [Root in postorder]
preorder: [1] [2 4 5] [3]
postorder: [4 5 2] [3] [1]
From here you can do this algorithm recursively with the left and right tree and in the end you get this:
1
/ \
2 3
/ \
4 5
Since every element is unique there is only one way to build the tree and therefore you can rebuild a tree from its postorder and preorder list.
In case you have elements that are the same you can't build a unique tree, example:
preorder: 1 X X 5 X
postorder: X 5 X X 1
from these lists you could create these two trees:
1 1
/ \ / \
X X X X
/ \ / \
X 5 5 X
I was playing with the orders a bit to understand them better and here are my findings:
Post-order - from the sequence you can always tell what is the root and what is the right-most child (ex. is 1,2,3,4,5 - 5 is the root and 4 is the right-most child)
Pre-order - from the sequence you can always tell what is the root and what is the left-most child (ex. is 1,2,3,4,5 - 1 is the root and 2 is the left-most child)
In-order - given a root vertex, you can always tell what is on the left and what is on the right (ex. is 1,2,3,4,5 and for the root 3 - 1,2 are on the left, 3,4,5 are on the right )
Now you can play with it. Having an in-order with either post-order or pre-order, you can easily reconstruct the tree because you can find the root and recursively find it always for the left/right branch. In case of having pre-order and post-order together, you can find the root and left-most children & right-most children. The problem happens in case the root has only left/right children, because you cannot tell which one it is and as such, you cannot easily reconstruct the tree.
However, as being asked, having the "full" binary tree, where every vertex has either both children or any, you don't have the problem with pre/post order combination and therefore every pair of orders will help you to reconstruct the tree. However only having one of the orders, you cannot reconstruct the tree (for example knowing only left child is not enough, you don't have information about which is the right one)
Suppose you had a tree w/ 3 nodes, all labelled the same. There are at least 3 such (not-necessarily full) trees, but all will have the same traversal arrays, no matter what order. That should answer your first question.
If we have V values for a search tree where the values are V= {1,2,3,4,5,6,7} inserted from right to left
And we are to order it to get the largest and shortest height possible -- how would we do it? Would it require the best and worst (lg2 (n+1)) case??
And would the orderings be unique?
Thanks -- I kinda understand but am not sure on what steps i should take.
The largest height is easy; put them in order:
1
\
2
\
...
With the smallest height, sort them, take the middle as the root, and put the two sides one either branch. Rinse and repeat.
3
/ \
2 5
/ / \
1 4 6
\
7
So... n for the first one, and log_2(n) for the second (rounded up).
The tallest such trees are created by inserting the values from a sorted sequence
1 2 3 4 5 6 7
or
7 6 5 4 3 2 1
The shortest tree is made by ordering the values via a recursive algorithm that finds the median then processes the left and right subtrees recursively:
4 2 1 3 6 5 7
This produces a tree of logarithmic height:
4
/ \
2 6
/ \ / \
1 3 5 7
Here the median is 4, so that goes first.
4
Now you have a partition for the left (1, 2, 3) and right (5, 6, 7). To order the left, start with its median, 2. Now you have 1 and 3 for its subtrees. These are 1 element sets so that's your base case.
4 2 1 3
Now process your right subtree (5, 6, 7), starting with 6.
4 2 1 3 6 5 7
I want to create a BST from a sorted linked list. I have solved the problem for recursively but was wondering how to write an iterative solution for the same without changing the complexity of the problem.
[EDIT]
Note: I do not want to implement my own stack.
[EDIT2]
The function that recursively calls itself be f. Pseudo code is given below. Call f with head pointer from main
node * f(int start_index, int end_index, node *ptr) {
if ( start>end) return NULL
middle_index = start_index + (end_index-start_index)/2
node *l_child = f(start_index, middle_index-1, ptr)
initialize parent with ptr's value
parent->left = l_child
ptr = ptr->next
parent->right = f(middle_index+1, end, ptr)
return parent
}
Assuming ahead of time that you want it to be like so, roughly:
_______
/ \
/ \ / \
/ \ / \
/ \ / \ / \ /
1 2 3 4 5 6 7
then you can explicitly solve for the structure. In this case, for a list of length L<2N for some integer N, and assuming you create all nodes and leave some leaves as "null" (or alternatively don't even construct those nodes), you have the total number of nodes in the tree equal to (2*2N)-1. Your nodes would look like:
12345678
/ \
1234 5678
/ \ / \
12 34 56 78
/ \ / \ / \ / \
1 2 3 4 5 6 7
I mentioned the size of the nodes because it should give us insight into how to proceed: there ought to be some way to enumerate {1,2}->12, {3,4}->34, {12,34}->1234, .... One way to proceed is to start grouping nodes from the bottom. For example, we could do this in N (3) passes:
step 1: 1 2 3 4 5 6 7
step 2: (1 2) (3 4) (5 6) (7 )
step 3: ((1 2) (3 4))((5 6) (7 ))
step 4: (((1 2) (3 4))((5 6) (7 )))
Another alternative is to use a stack to keep track of the higher level nodes as we group them.
Another way is to create an explicit formula for the structure. We create 7 nodes and set their children as follows: {1,2}, {3,4}, {5,6}, {7,null}, {12,34}, {56,78}, {1234,5678}. In particular if we index the nodes in a linear scheme, this pattern would be: 9={1,2}, 10={3,4}, 11={5,6}, 12={7,null}, 13={9,10}, 14={11,12}, 15={13,14}. Simply incrementing appears to give the exact pattern of a balanced binary tree. This will use no additional memory.
You can convert any recursive solution to an "iterative" solution by simulating a stack.