given k avl trees(T1, T2, ...Tk).
all the trees together have n different numbers(T1 nodes+ T2 nodes+...Tk nodes = n )
I want to sort all of them together and print the numbers sorted from the the smallest to the biggest with the best efficiency possible.
any help ?
On each AVL tree define a cursor (generator, iterator, ...) that will visit the nodes in-order.
Create a priority queue (like a binary min-heap) with k entries -- one for each AVL tree, and as key (priority) the value of the tree's current (cursor) node.
Then repeat as long as there are entries in the priority queue:
Pull the first entry from the priority queue. This gives you a tree with a current node that has the least value (compared to all other "current" nodes).
Output that current node's value.
Forward the tree's cursor to the next node (according to in-order traversal).
If this succeeds (i.e. there is a next node) then push this tree back on the priority queue with its new key (i.e. the value of its now current node). Otherwise, skip this step.
Related
Suppose I have a binary tree in which a node can have either 0,1 or 2 children. A cost value is associated with each node, and it can be {5,10,20,40}. The most optimal placement of a new node is under a node with same or lower cost value. For example- a new node with cost value 20 is best placed under a node with cost value 20, but can also be placed under nodes with cost values 5 and 10.
Primary requirement of this algorithm is to complete the left and right child of a node if it is required, i.e. if a node with cost value 10 has a left child with cost value 10, then a new node having cost value 10 will be made the right child of the above node . The secondary requirement is to maximize the overall depth of the tree.
The tree cannot be rearranged at any point of time. If an incoming node is of lesser value, then there is no penalty involved.
Given the above requirements, how can we decide the best position of an incoming new node in the tree ? Can we write a general algorithm for it ?
Initially, I thought to complete each level of the tree first, but I don't think it would be optimal.
The secondary requirement is to maximize the overall depth of the tree.
That's a bit unusual.
The quickest way:
sort your input values
fill all the minimal value nodes (5's) in respect with the first requirement (still unclear if both left-right nodes must be filled in before going down a level. If it must then the max depth will be log2(N5) If "going deep on left" is allowed without filling in the right, then the max depth tree will degenerate in list with all right nodes to null).Call this the master tree
make a tree from the next values (say 10-value nodes) and attach this tree to the deepest branch of the master tree
repeat step 3 as necessary
Note: this is the simplest concept, the implementation may take advantage from the fact the master tree is sorted at all time and get over with the initial sort.
We are given a tree with n nodes in form of a pointer to its root node, where each node contains a pointer to its parent, left child and right child, and also a key which is an integer. For each node v I want to add additional field v.bigger which should contain number of nodes with key bigger than v.key, that are in a subtree rooted at v. Adding such a field to all nodes of a tree should take O(n log n) time in total.
I'm looking for any hints that would allow me to solve this problem. I tried several heuristics - for example when thinking about doing this problem in bottom-up manner, for a fixed node v, v.left and v.right could provide v with some kind of set (balanced BST?) with operation bigger(x), which for a given x returns a number of elements bigger than x in that set in logarihmic time. The problem is, we would need to merge such sets in O(log n), so this seems as a no-go, as I don't know any ordered set like data structure which supports quick merging.
I also thought about top-down approach - a node v adds one to some u.bigger for some node u if and only if u lies on a simple path to the root and u<v. So v could update all such u's somehow, but I couldn't come up with any reasonable way of doing that...
So, what is the right way of thinking about this problem?
Perform depth-first search in given tree (starting from root node).
When any node is visited for the first time (coming from parent node), add its key to some order-statistics data structure (OSDS). At the same time query OSDS for number of keys larger than current key and initialize v.bigger with negated result of this query.
When any node is visited for the last time (coming from right child), query OSDS for number of keys larger than current key and add the result to v.bigger.
You could apply this algorithm to any rooted trees (not necessarily binary trees). And it does not necessarily need parent pointers (you could use DFS stack instead).
For OSDS you could use either augmented BST or Fenwick tree. In case of Fenwick tree you need to preprocess given tree so that values of the keys are compressed: just copy all the keys to an array, sort it, remove duplicates, then substitute keys by their indexes in this array.
Basic idea:
Using the bottom-up approach, each node will get two ordered lists of the values in the subtree from both sons and then find how many of them are bigger. When finished, pass the combined ordered list upwards.
Details:
Leaves:
Leaves obviously have v.bigger=0. The node above them creates a two item list of the values, updates itself and adds its own value to the list.
All other nodes:
Get both lists from sons and merge them in an ordered way. Since they are already sorted, this is O(number of nodes in subtree). During the merge you can also find how many nodes qualify the condition and get the value of v.bigger for the node.
Why is this O(n logn)?
Every node in the tree counts through the number of nodes in its subtree. This means the root counts all the nodes in the tree, the sons of the root each count (combined) the number of nodes in the tree (yes, yes, -1 for the root) and so on all nodes in the same height count together the number of nodes that are lower. This gives us that the number of nodes counted is number of nodes * height of the tree - which is O(n logn)
What if for each node we keep a separate binary search tree (BST) which consists of nodes of the subtree rooted at that node.
For a node v at level k, merging the two subtrees v.left and v.right which both have O(n/2^(k+1)) elements is O(n/2^k). After forming the BST for this node, we can find v.bigger in O(n/2^(k+1)) time by just counting the elements in the right (traditionally) subtree of the BST. Summing up, we have O(3*n/2^(k+1)) operations for a single node at level k. There are a total of 2^k many level k nodes, therefore we have O(2^k*3*n/2^(k+1)) which is simplified as O(n) (dropping the 3/2 constant). operations at level k. There are log(n) levels, hence we have O(n*log(n)) operations in total.
Input:
a rooted tree with n nodes;
each node p has positive integer weight w(p);
a node can have more than two children.
Problem:
divide the tree into k subtrees/partitions (obviously by removing k-1 edges);
subtree weight W(p) is the weight of all the nodes in a subtree rooted at node p;
all the subtrees should be weighted as evenly as possible - the difference between min(W(p)) and max(W(p)) should be as small as possible.
I've yet to find a suitable algorithm for this. Where should I start? Tips, instructions and pseudocode appreciated.
Assume you can't modify the tree other than to remove edges to create subtrees.
First understand that you cannot guarantee that by simply removing edges that you will have subtrees within an arbitrary bound. You can create tree that when you split them there is no way to create subtrees within a target bound. For example:
a(b(c,d,e,f),g)
You cannot split that into two balanced sections. The best you can do is remove the edge from a to b:
a(g) and b(c,d,e,f)
Also this criteria is a little underdefined when k > 2. What is better a split 10,10,10,1 or 10,10,6,5?
But you can come up with a method to split trees up in the most balanced way possible.
Implement you tree such that each node holds a count of all of its children. You can add this pretty efficiently to any tree. ( E.g. when you add a node you have to iterate up the chain of parent node incrementing the count. Remove a node and you iterate up subtracting from the count )
Then starting from the root iterate down, in a breadth first manner until you find a set of nodes that dominate child nodes in a way that is most balanced. I don't have an algorithm for this at the ready - but I think you can find one pretty readily.
I think something where when you want to divide into k subtrees you create an array of k tree roots. One of those nodes must always be the root of the current tree, then you iterate down looking for nodes to replace on of the k-1 candidates that improves the partitioning. You'll want some kind of terminating condition where you don't interate down to every leaf node. E.g. it never makes sense to subdivide anything by the largest candidate node.
Problem : Given a rooted Tree T containing N nodes. Each node is numbered form 1 to N, node 1 being the root node. Also, each node contains some value. We have to do three kind of queries in the given tree.
Query 1::
Given a node nd, you have to find the sum of the values of all the nodes of the subtree rooted at nd and print the answer.
Query 2::
Given a node nd, you have to delete the subtree rooted at nd, completely (including node nd).
Query 3::
Given a node nd and some integer v, you have to add a child to node nd having value equal to v.
Constraints : N will be of the order of 100000. And total number of queries wil also be of the order 100000. So, I can't to DFS traversal every time.
My Idea: My solution is offline . I will first find all the nodes that are added to the tree at-least once and make the corresponding tree. Then I will do pre-order traversal to the tree and convert it into an array where a subtree will always appear continuously. Then I can use segment tree data structure to solve the problem. My algorithm will be thus O(QlogN), where Q is the total number of queries. However, I am looking for a "online" solution which is efficient. I mean, I have perform each query as soon as it is asked. I can not store all the queries first then perform them one by one.
Any help is appreciated a lot!
Thanks.
Assuming tree is balanced, with two extra parameters in every node you can solve it in o(qlogn).
With every node maintain a sum whose value will be equal to the sum of values of nodes in the subtree rooted at that and maintain parent as well.
With the above two requirements, query one just reduces to returning sum plus the value at that node(o(1)). query two reduces to just subtracting sum plus the value of node from every parent of that node till you reach the root(o(logn)). query three just reduces to adding v to every parent of that node till you reach the root(o(logn)).
Suppose each object has this form: (key, priority) i.e., (0, 3), (5, 7).
Say you are given two numbers, x and y.
What data structure would you use to return the highest-priority object whose key is between x and y?
I think priority queue can be a good solution, but I have no idea how to modify it to return the highest-priority object in the given range.
Starting with a binary search tree, add two fields to each node: the priority, and (a pointer to) the highest-priority node in the subtree (see CLRS Chapter 14 for more on how to carry out this augmentation).
Now, to do a range query, start the search normally until the current node's key lies in the range. Examine that node and, using symmetric variants of the following procedure to identify O(log n) candidates that include the highest-priority node in range, the left and right subtrees of the current node. The following procedure is for the left subtree.
If the root is in range, consider it for highest priority, along with the highest-priority node in its right subtree (cached in the node). Continue with the left subtree. If the root is not in range, continue with the right subtree.
This problem is known as RMQ (Range Minimum/Maximum Query).
The best data structure to use in your case is Segment Tree.
It is a hard structure to get right the first time, but keep trying: this solves exactly your problem.