What is the minimal amount of space needed to find out which level in binary tree (random or BST) has the most number of nodes?
If you are allowed to destroy the tree, then you can convert the tree to a linked list while doing a bfs of the tree, essentially simulating a queue with the tree itself!
You can find information about that here: Convert a binary tree to linked list, breadth first, constant storage/destructive
This requires only O(1) space as you have reused the nodes of the tree.
O(1)
Traverse the BT (Binary Tree) in Breadth-First-Search approach. Push nodes with mentioning the level of it. You will traverse all nodes in a level and then go to the next level. So just maintain the a maximum variable and keep updating it.
The Queue(for BST) could take space in O(2^(log(n) -1)).
Related
I have two binary trees. One, A which I can access its nodes and pointers (left, right, parent) and B which I don't have access to any of its internals. The idea is to copy A into B by iterating over the nodes of A and doing an insert into B. B being an AVL tree, is there a traversal on A (preorder, inorder, postorder) so that there is a minimum number of rotations when inserting elements to B?
Edit:
The tree A is balanced, I just don't know the exact implementation;
Iteration on tree A needs to be done using only pointers (the programming language is C and there is no queue or stack data structure that I can make use of).
Rebalancing in AVL happens when the depth of one part of the tree exceeds the depth of some other part of the tree by more than one. So to avoid triggering a rebalance you want to feed nodes into the AVL tree one level at a time; that is, feed it all of the nodes from level N of the original tree before you feed it any of the nodes from level N+1.
That ordering would be achieved by a breadth-first traversal of the original tree.
Edit
OP added:
Iteration on tree A needs to be done using only pointers (the
programming language is C and there is no queue or stack data
structure that I can make use of).
That does not affect the answer to the question as posed, which is still that a breadth-first traversal requires the fewest rebalances.
It does affect the way you will implement the breadth-first traversal. If you can't use a predefined queue then there are several ways that you could implement your own queue in C: an array, if permitted, or some variety of linked list are the obvious choices.
If you aren't allowed to use dynamic memory allocation, and the size of the original tree is not bounded such that you can build a queue using a fixed buffer that is sized for the worst case, then you can abandon the queue-based approach and instead use recursion to visit successively deeper levels of the tree. (Imagine a recursive traversal that stops when it reaches a specified depth in the tree, and only emits a result for nodes at that specified depth. Wrap that recursion in a while or for loop that runs from a depth of zero to the maximum depth of the tree.)
If the original tree is not necessarily AVL-balanced, then you can't just copy it.
To ensure that there is no rebalancing in the new tree, you should create a complete binary tree, and you should insert the nodes in BFS/level order so that every intermediate tree is also complete.
A "complete" tree is one in which every level is full, except possibly the last. Since every complete tree is AVL-balanced, and every intermediate tree is complete, there will be no rebalancing required.
If you can't copy your original tree out into an array or other data structure, then you'll need to do log(N) in-order traversals of the original tree to copy all the nodes. During the first traversal, you select and copy the root. During the second, you select and copy level 2. During the third, you copy level 3, etc.
Whether or not a source node is selected for each level depends only on its index within the source tree, so the actual structure of the source tree is irrelevant.
Since each traversal takes O(N) time, the total time spent traversing is O(N log N). Since inserts take O(log N) time, though, that is how long insertion takes as well, so doing log N traversals does not increase the complexity of the overall process.
Given a very large binary tree (i.e. with millions of nodes), how to handle determining the number of nodes in the tree? In other words, given the root node of this tree to a function, the function should return the number of nodes in the tree.
Or let's say how do you check if the Binary Tree is BST if the tree has very large number of nodes?
Walk all nodes and check whatever conditions/metric you need. There is nothing else you can do without additional knowledge about the tree.
You can enforce particular conditions at the time when tree is created (i.e. must be balanced/sorted/whatever) or collect information about tree at creation time (i.e. store and constantly update number of children).
To check if it's a VALID bst you have to visit every node depth first and ensure each node is smaller than the previous.
If you want to evaluate how long that will take for a balanced BST you could get a quick approximation of the size by counting the length of one leg, I believe the total size will be between 2^(n-1) and 2^n-1 inclusive
How can you convert Binary Tree to Binary Search Tree with O(1) extra space ?
Converting an unordered binary tree into an ordered binary search tree is trivial, but a bit more difficult to do fast.
Here's a naive implementation that should satisfy your criteria, I will not describe the actual steps to take, just the overall algorithm.
Grab a random leaf node from your existing tree
Unlink the leaf node from your existing tree
Make the node the root of your new binary search tree
Grab another random leaf node from your existing tree
Unlink that node from your existing tree
Find the right spot for, and link the node, into your new binary search tree
Repeat step 4-6 until the original tree is empty
You should require only a few variables, like the parent of the leaf node you're unlinking (unless the nodes has parent-links), the root node of the new tree, and a couple of temporary variables, all within your O(1) space criteria.
This will not produce an optimal binary search tree. For that you need to either sort the nodes before adding them, and adding them in the right order, or use a balancing binary search tree, like a red-black tree or a splay tree.
Convert Binary Tree to a doubly linked list- can be done inplace in O(n)
Then sort it using merge sort, nlogn
Convert the list back to a tree - O(n)
Simple nlogn solution.
a BST(binary search tree) T is given.
how to find the nth smallest element of T ?
A binary search tree is effectively sorted, so you just need to go through the tree in-order and get to the nth spot. If the tree is fully balanced, you can calculate the spot to get to.
If the binary search tree is not fully balanced, then you need to do a recursive search to find the nth smallest element. This can be hugely accelerated by having each node store the number of subnodes pointed to by each of its branch pointers, effectively turning the search into a binary one. However, this add overhead on tree updates as each insertion or deletion now requires a leaf-to-root traversal to update the node counts.
Alternatively, you can keep the tree balanced, and use the above answer.
I want to sum all the values in the leaves of a BST. Apparently, I can't get to the leaves without traversing the whole tree. Is this true? Can I get to the leaves without taking O(N) time?
You realize that the leaves themselves will be at least 1/2 of O(n) anyway?
There is no way to get the leaves of a tree without traversing the whole tree (especially if you want every single leaf), which will unfortunately operate in O(n) time. Are you sure that a tree is the best way to store your data if you want to access all of these leaves? There are other data structures which will allow more efficient access to your data.
To access all leaf nodes of a BST, you will have to traverse all the nodes of BST and that would be of order O(n).
One alternative is to use B+ tree where you can traverse to a leaf node in O(log n) time and after that all leaf nodes can be accessed sequentially to compute the sum. So, in your case it would be O(log n + k), where k is the number of leaf nodes and n is the total number of nodes in the B+ tree.
cheers
You will either have to traverse the tree searching for nodes without children, or modify the structure you are using to represent the tree to include a list of the leaf nodes. This will also necessitate modifying your insert and delete methods to maintain the list (for instance, if you remove the last child from a node, it becomes a leaf node). Unless the tree is very large, it's probably nice enough to just go ahead and traverse the tree.