Let S be a dynamic set of integers. Let n = |S|. Describe a data structure on S to
support the following operations on S with the required performance guarantees:
• Insert a new element to S in O(log n) time.
• Delete an element from S in O(log n) time.
• Report the k smallest elements of S in O(k) time, for any k satisfying 1 ≤ k ≤ n.
Your structure must consume O(n) space at all times.
could i simply build an AVL tree and then preform in order traversal printing out first 3 elements?
Use a priority queue, which uses O(n) space. Insert and delete are both O(log n) operations. Find-min is O(1), followed by remove-min which is O(k), which you can repeat three times.
Your suggested solution does not work in O(k) time. Starting an in-order traversal takes O(log n) time. Even when you stop after you find one element, you still need to get to the left-most leaf first.
I can think of two solutions:
Use a skip-list, it has O(log n) insertion and deletion and the underlying list is sorted. However, the time complexity of the insertion and deletion is average and not worst-case.
Use a modified AVL-tree, keep a dedicated pointer to the left-most node and update it on insertions and deletions. Also nodes must have pointers to their parent node, so that you could do in-order traversal starting at the left-most node. Or use a threaded tree.
ive decided to store and updated left most node pointer at the root, and pointers to predecessor and successor at every node
thus on every insertion it costs O(logn) for insertions and O(logn)+O(logn) to find both predecessor and successor, O(logn)+O(logn)+O(logn) = O(logn)
these pointer also allow for the update of effected node pointers after insertion in O(1) to travel to predecessor or successor respectively and update there pointers also in O(1)
having pointer to left most node at the root means travelling there is O(1) and then traversing the successor and printing first k nodes in O(k) time.
Related
Fibonacci heaps are efficient in an amortized sense, but how efficient are they in the worst case? Specifically, what is the worst-case time complexity of each of these operations on an n-node Fibonacci heap?
find min
delete-min
insert
decrease-key
merge
The find-min operation on a Fibonacci heap always takes worst-case O(1) time. There's always a pointer maintained that directly points to that object.
The cost of a delete-min, in the worst-case, takes time Θ(n). To see this, imagine starting with an empty heap and doing a series of n insertions into it. Each node will be stored in its own tree, and doing a delete-min the heap will coalesce all these objects into O(log n) trees, requiring Θ(n) work to visit all the nodes at least once.
The cost of an insertion is worst-case O(1); this is just creating a single node and adding it to the list. A merge is similarly O(1) since it just splices two lists together.
The cost of a decrease-key in the worst case is Θ(n). It's possible to build a degenerate Fibonacci heap in which all the elements are stored in a single tree consisting of a linked list of n marked nodes. Doing a decrease-key on the bottommost node then triggers a run of cascading cuts that will convert the tree into n independent nodes.
I almost agree with the great answer from #templatetypedef.
There cannot be a tree of a classical Fibonacci heap with $n$ marked nodes. This would mean that the height of the tree is O(n), but since for each subtree of rank $k$ its children are of ranks $\geq 0, \geq 1, ... , \geq k-1$. It is easy to see that the depth of the tree is at most O(logn). And therefore a single Decrease-key operation can cost O(logn).
I checked this thread, and it takes some modification of the Fibonacci heap, as it has marked node in the root list and does operation which do not belong to the Fibonacci heap.
I'm looking for a data structure that supports the following operations for
integer keys k ranging from 0 to M-1.
O(1) or O(log n) insert(k), erase(k), lookup(k).
O(1) or O(log n) for the special operation find_missing_key() which returns any key not currently present in the structure.
O(n) or O(n log n) space. In particular. should not be O(M).
An obvious implementation would be a "list-of-free-keys" structure, implemented as a heap; but that would take O(M) space. Is there some data structure that fulfills all of the requirements?
Use a binary segment tree.
Each node in the tree represents a range of integers [a,b], and is either a leaf [a,a] or divides into two nodes representing the ranges [a,m] and [m+1, b] where m is (a+b)/2.
Only expand nodes when necessary, so initially we just have a root node for the range [0,M-1] (or [0,M) if you prefer)
In each node, keep a count of how many used/free spots you have in that subtree.
Insertion, lookup, and deletion of x is O(log n): Just keep subdividing until you reach [x,x], and update everything on the path from that node to the root.
find_missing_key is also O(log n): Since you know the size of each segment and how many free elements are in it, you can decide at each node whether to go left or right in order to find a free element.
(EDIT: Incidentally, this also allows you to find the first, or last, or even the i_th free element, at no additional cost.)
I want to Find Maximum number of comparison when convert min-heap to max-heap with n node. i think convert min-heap to max-heap with O(n). it means there is no way and re-create the heap.
As a crude lower bound, given a tree with the (min- or max-) heap property, we have no prior idea about how the values at the leaves compare to one another. In a max heap, the values at the leaves all may be less than all values at the interior nodes. If the heap has the topology of a complete binary tree, then even finding the min requires at least roughly n/2 comparisons, where n is the number of tree nodes.
If you have a min-heap of known size then you can create a binary max-heap of its elements by filling an array from back to front with the values obtained by iteratively deleting the root node from the min-heap until it is exhausted. Under some circumstances this can even be done in place. Using the rule that the root node is element 0 and the children of node i are elements 2i and 2i+1, the (max-) heap condition will automatically be satisfied for the heap represented by the new array.
Each deletion from a min-heap of size m requires up to log(m) element comparisons to restore the heap condition, however. I think that adds up to O(n log n) comparisons for the whole job. I am doubtful that you can do it any with any lower complexity without adding conditions. In particular, if you do not perform genuine heap deletions (incurring the cost of restoring the heap condition), then I think you incur comparable additional costs to ensure that you end up with a heap in the end.
Suppose I have a balanced BST (binary search tree). Each tree node contains a special field count, which counts all descendants of that node + the node itself. They call this data structure order statistics binary tree.
This data structure supports two operations of O(logN):
rank(x) -- number of elements that are less than x
findByRank(k) -- find the node with rank == k
Now I would like to add a new operation median() to find the median. Can I assume this operation is O(1) if the tree is balanced?
Unless the tree is complete, the median might be a leaf node. So in general case the cost will be O(logN). I guess there is a data structure with requested properties and with a O(1) findMedian operation (Perhaps a skip list + a pointer to the median node; I'm not sure about findByRank and rank operations though) but a balanced BST is not one of them.
If the tree is complete (i.e. all levels completely filled), yes you can.
In a balanced order statistics tree, finding the median is O(log N). If it is important to find the median in O(1) time, you can augment the data structure by maintaining a pointer to the median. The catch, of course, is that you would need to update this pointer during each Insert or Delete operation. Updating the pointer would take O(log N) time, but since those operations already take O(log N) time, the extra work of updating the median pointer does not change their big-O cost.
As a practical matter, this only makes sense if you do a lot of "find median" operations compared to the number of insertions/deletions.
If desired, you could reduce the cost of updating the median pointer during Insert/Delete to O(1) by using a (doubly) threaded binary tree, but Insert/Delete would still be O(log N).
My assignment is to create an AVL Tree from a sorted array list of values in O(n) time where n is the number of values
I have been working on this but I cannot get O(n) time, the best I can get is O(nlog(n))
My problem is that every time a node that causes the tree to be unbalanced is inserted, I have to do another loop to find the node that is unbalanced and apply rotation(s) to balance the tree again.
Any help is greatly appreciated, thanks!
How about just creating a complete balanced tree, with a few nodes at the lowest level possibly missing, e.g., for 6 elements, create
o
/ \
o o
/ \ /
o o o
Then do an inorder walk, and when you visit the i-th node, set its key to A[i].
This is a valid AVL tree, since every node has a left and right child whose heights differ by at most one.
The original tree can be constructed in O(n), and the inorder walk in O(n), so the complexity is O(n).
Incidentally, on a semirelated note, there's a technique called heapify for building a heap (mix or max) out of an array of integers that's O(n) for a length n array, even though the insertion into a heap is O(log n) - the trick is to do it bottom up.
Inserting is O(logn), so true, nobody can do better than O(nlogn) when inserting. Really, you shouldn't insert into the AVL-tree. You should just create the tree. Create all the nodes and pick the values from the array as you are constructing new nodes. Don't find/search the value you need, just take it, the array is sorted.
Given a list that contains 5 elements and is sorted, for example [1,2,3,4,5], what would be the root of the tree? How about for 7 elements? 10? ...?
After you got the root, then what would be the root of the left subtree. What's the list to look at? Which part of the list do you have to store in the left subtree?
That's all.