Here is one implementation of the remove method for BST. I quote from there:
Removing an element from a search tree, although tricky,
is conceptually straight-forward with one (common) exception: removing the element at a
node with two non-null children. In this case, the solution is either:
removeMax: remove the maximum (rightmost) node from the left subtree
and replace the root's value with the value of the removed node.
removeMin: remove the minimum (leftmost) node from the right subtree
and replace the root's value with the value of the removed node.
In either case the search tree's order structure is preserved.
If you look at this binary tree,
I want to remove 8 and if I choose to pick element from leftTree, using removeMax, I will choose 7 according to the above definition.
but I need to choose 13 from right Tree using removeMin and that breaks the BST.
am I not understanding this correctly?
The way remove works is getting the either the maximum from the leftTree or minimum from the rightTree and replace the node to be removed with its data.
Despite the visual appearance, the leftmost node of the right subtree above is ten, not 13. Reaching 13 requires moving right (from ten to 14), so 13 cannot be the leftmost node. If you choose ten, the BST property would not be broken.
The right subtree has three nodes - 10, 14, and 13.
10
\
\
14
/
13
Ten (at the top) has no left subtree, so it is the leftmost node of the right subtree.
what if 10's leftnode is not null but some node?
Then the tree would look like this:
10
/ \
/ \
9 14
/
13
so the leftmost node would be nine, not ten. Then the algorithm that you describe would pick nine for removal, which would again preserve the BST property.
The minimum value from the right subtree is 10, not 13.
Something that might help if you need a visual mnemonic: the minimum value of a right subtree is the "leftmost descendent of the right child."
Related
This is for a homework problem -
I need to find the median of a Binary Search Tree in O(h) time - meaning, I cant go through the whole tree to find it. I need to find the median by going through the left or right side of the tree, in a recursion solution.
I've placed an index into each node of the BST, using inorder traversal.
So if a BST has 99 nodes, the smallest node has an index of 1, the next smallest has index of 2 etc etc...while the largest node has index of 99. THis indexing is also required of the assignment.
So whichever side is heavier, has the median.
So here's what I was thinking:
if the left side has more nodes median is on the left. if right side has more nodes, median is on the right. if the left and right sides have equal num of nodes, median is the main root of the whole tree.
But I can't think of how the nodes' indexes would play a role in any of this. I was thinking of using the difference of 2 nodes' indexes to see if 1 side is heavier, but this would require me to go through the whole tree I think, so this would be O(n).
Please set me on a clearer path or a hint or 2.
I am working on below interview question:
Given a singly linked list where elements are sorted in ascending
order, convert it to a height balanced BST.
For this problem, a height-balanced binary tree is defined as a binary
tree in which the depth of the two subtrees of every node never differ
by more than 1.
I am trying to understand below solution and its complexity? Can someone help me understand how it works? Is below solution O(n) time complexity and O(log n) space complexity?
Also is below algorithm better than "counting the number of nodes in the given Linked List. Let that be n. After counting nodes, we take left n/2 nodes and recursively construct the left subtree. After left subtree is constructed, we allocate memory for root and link the left subtree with root. Finally, we recursively construct the right subtree and link it with root. While constructing the BST, we also keep moving the list head pointer to next so that we have the appropriate pointer in each recursive call"
public TreeNode toBST(ListNode head) {
if(head==null) return null;
return helper(head,null);
}
public TreeNode helper(ListNode head, ListNode tail){
ListNode slow = head;
ListNode fast = head;
if(head==tail) return null;
while(fast!=tail && fast.next!=tail){
fast = fast.next.next;
slow = slow.next;
}
TreeNode thead = new TreeNode(slow.val);
thead.left = helper(head,slow);
thead.right = helper(slow.next,tail);
return thead;
}
BST-construction
A balanced tree can be constructed from a sorted list by subdividing the list into two equally long lists with one element in the middle being used as a root. E.g.:
1. [1, 2, 3, 4, 5, 6, 7]
2. 4
/ \
[1, 2, 3] [5, 6, 7]
3. 4
/ \
2 6
/ \ / \
1 3 5 7
Even if the two sublists differ by one element, they can at most differ by 1 in their height, thus making the tree balanced. By taking the middle element of the list the resulting tree is guaranteed to be a BST, since all smaller elements are part of the left subtree and all larger elements of the right subtree.
slow and fast
Your code works using two iterators, where one (fast) iterates over nodes twice as fast as the other (slow). So when fast has reached either the tail or the node right before the tail of the list, slow must be at the node in the middle of the list, thus dividing the list into two sublists of same length (up to at most one element difference), which can then be recursively processed as shown in the above diagramm.
Runtime Complexity
The algorithm runs in O(n lg n). Let's start with the recurrence of helper:
T(n) = n / 2 + 2 * T(n / 2)
T(1) = 1
In each call of helper, we must find the middle-node of the linkedlist defined by the two parameters passed to helper. This can only be done in n / 2 steps, since we can only walk linearly through the list. In addition, the helper is called recursively twice on linkedlists of half the size of the original list to build the left and right subtree.
Applying the Master-theorem(case 2) to the above recurrence, we get O(n lg n).
Space complexity
Space-complexity also needs to take the produced output-structure into account. Since each element of the input-linked list is converted into a node in the BST, the complexity is O(n).
EDIT
If the output is ignored, the space-complexity is solely dependent on the recursion-depth, which in turn is O(lg n), thus making the space-complexity O(lg n).
I need a JAVA code that could help me find the height of the Minimum spanning tree.
Basically i m looking for an extension of the
Prim's/Kruskal's algo that not only gives the height of the MST but also gives its height.
Thanks in advance.
Take as the root vertex one of the tree's centers and calculate the maximal distance from the chosen center to the leaf nodes.
The height can the be calculated in the following way:
set the height to 0
while there are at least 3 remaining vertices:
delete all leaf vertices
height := height+1
if 2 vertices remain:
height := height+1
the remaining vertices are the centers of the tree.
The time complexity is O(n).
A practical way of calculating the height would be to combine all leaf nodes int a single node that serves as a root, then calculate the MST of that modification and the height as the maximum distance from generated root node to the newly generated leaf nodes.
I am not writing the code here, just giving you a hint.
In every node keep a variable that stores the height/depth of that node.
So, depth for starting node will be 0. Now, whenever you add a edge to the MST, increase the depth of the new node by 1.
Currently you have the following discovered nodes with the following depth.
a 0
b 1
c 1Now suppose you want to add the edge from c to d, so the depth of node d will be depth(c)+1, i.e 1+1=2.
Also, you can keep a track of the maximum depth among all nodes at each step of the algorithm.
So, finally answer will be the maximum depth among all the nodes of the tree.
Suppose that there's a binary tree like the one below that needs to be stored in an array.
7
/ \
1 10
/\
9 11
And I found that the formula for storing the nodes in the array begins with storing the root node at position 0, and then for every node at index i, its children are placed at indices (i*2)+1 and (i*2)+2. And if the index of either child is greater than the array.length - 1, then that node does not have children.
So I begin by putting 7 at position 0, then its children 1 and 10 at position i2+1 and i2+2 which would be 1 and 2:
|7|1|10| | | |
0 1 2 3 4 5
Now, I'm stuck with node 1 which does not have any children. What should I put as its children?
Is it OK to put some default value that would represent the absence of a node, for example -1, like this:
|7|1|10|-1|-1|9|11|
0 1 2 3 4 5 6 7
This algorithm for storing a binary tree in an array is designed for trees such that every branch of the tree starting from the root node is of the same length: the array size is based on the greatest depth within the tree, and then it assigns an array position for every tree position of equal or lesser depth. If you have many different branch lengths, this may not be the correct algorithm for you. If your branch lengths are mostly the same depth but are sometimes empty near the end of the tree, placing a 'null' value such as -1 or Integer.MIN_VALUE may be an appropriate solution, as long as you know that you will not normally need to place any -1 values into the tree.
If you happen to know that you will only be missing elements from the greatest depth level of your tree (as in the example you provided), and the left/right order of the tree does not matter, you can instead simply reorder your tree such that the empty values are always in the bottommost, rightmost positions, which is also the set of positions at the end of your array, thus making your tree a complete binary tree. Then, you need only remember the number of elements in the tree, which is one greater than the index of the last non-null value. Diagrammed:
7
/ \
10 1
/\
9 11
-->
|7|10|1|9|11|0|0|
0 1 2 3 4 5 6
length = 5 or lastIndex = 4
I was thinking of using values which will break binary tree property at this point. In a general binary tree Left is always smaller and right is bigger than current node. If encounter higher on left or lower on right means end nodes.
Consider the following code:
public int heightOfBinaryTree(Node node)
{
if (node == null)
{
return 0;
}
else
{
return 1 +
Math.max(heightOfBinaryTree(node.left),
heightOfBinaryTree(node.right));
}
}
I want to know the logical reasoning behind this code. How did people come up with it? Does some have an inductive proof?
Moreover, I thought of just doing a BFS with the root of the binary tree as the argument to get the height of the binary tree. Is the previous approach better than mine?Why?
if (node == null)
{
return 0;
}
The children of leaf nodes are null. Therefore this is saying that once we've gone past the leaves, there are no further nodes.
If we are not past the leaf nodes, we have to calculate the height and this code does so recursively.
return 1 +
The current node adds a height of 1 to the height of the subtree currently being calculated.
Math.max(heightOfBinaryTree(node.left),
heightOfBinaryTree(node.right));
We recursively calculate the height of the left subtree (node.left) and right subtree (node.right). Since we're calculating the maximum depth, we take the maximum of these two depths.
I've shown above that the recursive function is correct. So calling the function on the parent node will calculate the depth of the entire tree.
Here's a graphical representation of the height of a tree from this document. h is the height of the tree, hl and hr are the heights of the left and right subtrees respectively.
Moreover, I thought of just doing a
BFS with the root of the binary tree
as the argument to get the height of
the binary tree. Is the previous
approach better than mine?Why?
The code you provided is a form of DFS. Since you have to process all nodes to find the height of the tree, there will be no runtime difference between DFS and BFS, although BFS will use O(N) memory while DFS will use O(logN) memory. BFS is also slightly more complex to code, since it requires a queue while DFS makes use of the "built-in" recursive stack.
The logic behind that code is:
since a node will have two children, the height of the Tree will be maximum of the heights of tree whose roots are the left child and right child, and of course +1 for the walk to the children.
As you can see, the description above is recursive and so is the code.
BFS should also do, but it would be an overkill as both implementation and space/time complexity.
There is a say, recursive functions though hard to understand, but are very elegant to implement.
The height of a tree is the length of longest downward path from it's root.
This function is a recursive way to count the levels of a binary tree. It just increments counters as it descends the tree, returning the maximum counter (the counter on the lowest node).
I hope I have helped.
It's a recursive function. It's saying the height of a tree is 1 + the height of its tallest branch.
Is BFS a breadth first search? I'm not sure what difference there would be in efficiency, but I like the simplicity of the recursive function.
To extend more on the answers and elaborate more on recursion plus recursive call stack.
Suppose the tree
2
/\
5 9
/
0
lets suppose the left sub-tree first, root(2) called the heightOfBinaryTree method on the left sub-tree
The call stack of the method in question will be as follows
node(5) calls node(0)
node(0) calls node(null)
node(null) breaks the recursive loop
consider that fact these calls are made before the method returned anything.
iterating back on the recursive call stack, this is where each node return its output.
node(null) returned 0 -> 0
node(0) returned (return from node(null) + 1) -> 1
node(5) returned (return from node(0) + 1) -> 2
Same goes for the right sub-tree. If we compare the output from both left and right sub-tree we will have the height.