Given an sorted array in descending order, what will be the time complexity to delete the minimum element from this array?
================================================
My take the minimum element will be at last position so O(n) to find it? or should I apply Binary search since array is sorted or simply O(1) to reach at the end?
It really depends on what you mean "delete from the array." You have an array, sorted in descending order, and you want to delete the minimum element.
Let's say that the array is [5, 4, 3, 2, 1]. You know how large the array is, so finding the minimum element is O(1). You just index a[a.length-1].
But what does it mean to delete the last element? You can easily replace the value there with a sentinel value to say that the position is no longer used, but then the next time you tried to get the minimal element, you'd have to visit a[a.length-1], and then do a reverse scan to find the first used element. That approaches O(n) as you remove more items.
Or do you keep a counter that tells you how many values in the array are actually used? So you'd have a variable, count, to tell you which is the last element. And when you wanted to get the minimal element you'd have:
smallest = a[count];
count = count-1;
That's still O(1), but it leaves unused items in the array.
But if you want to ensure that the array length always reflects the number of items are in it, then you have to re-allocate the array to be smaller. That is O(n).
So the answer to your question is "It depends."
Since the array is sorted in descending order, the minimum element will be always guaranteed to be in last location of array, assuming there are no duplicates in the array. Deletion can be done in O(1).
If you need to do a series of deletions on the array, then you may want to adjust the deleted indices and point to the correct end location of the array. This can be done in constant time.
Hence to sum it up, the total time complexity would be O(1)
Related
I read it somewhere that deletion of an element is faster in an unsorted array but I am not sure if that's correct.
According to my understanding if we want to delete some particular element then in the case of a sorted array it will take O(log N) time to search it and finally delete it but in the case of the unsorted array it may take in worst case O(N) time to search it linearly before we finally delete it.
So how is this possible?
Summarising all existing answers,
(And adding a few of my points)
There are two processes we need to consider when we delete an element from any array.
Searching for the element in consideration
Deletion of that element
Note : In the below explanation, n is the total number of elements in the array.
Searching
In a sorted array, we can use Binary Search to find the array element to be deleted. The time complexity of Binary Search is O(log n)
In an unsorted array, we must use Linear Search to find the array element to be deleted. The time complexity of Linear Search is O(n)
Deletion
The removal of an element from any array, is done with a time complexity of O(1).
But the deletion process also includes what must be done after the removal of the element!
In a sorted array, all the elements to the right of the deleted element must be shifted one index to the left, to fill the space left behind by the deleted element and to maintain sorted order. Therefore, the worst-case time complexity is O(n)
In an unsorted array, we can fill the space left by the deleted element, with the last element in the array, since the array is unsorted anyway. The time complexity for this process is O(1)
CONCLUSION :
Sorted Array :
Searching : O(log n)
Removal : O(n)
Unsorted Array :
Searching : O(n)
Removal : O(1)
Deletion of an element is faster in a sorted array than in an unsorted array.
This is because you can binary search over a sorted array to find the element specified.
An unsorted array has to check every single element one by one (linear search) to find the element to delete.
The delete operation itself is the same time complexity for both.
O(log N) takes less time to execute than O(N).
Deleting an element from an array is a O(n) operation if you physically remove that element from the array. That's because all the elements to the right of the deleted element must be shifted. It's only an O(1) operation if the element is at the end of the array so we can pop it.
Now, in an unsorted array you can just swap the found element with the element at the end of the array in O(1) and pop from the end one element, also in constant time.
But in a sorted array, if you want to keep it sorted, you can't do that. You have to physically remove the element to keep the array sorted.
So, to make it clear, you need explicitly say that removing an element from a sorted array and keeping it sorted is O(n). If you don't care about it being sorted, you can remove it in O(1). The searching is logarithmic, so this becomes logarithmic. But you can only do this once. Because after that the array isn't sorted anymore and you can't search for your element in log n time.
Sorted array has an order that help us to find given element in O(logN) time. But in unsorted array we have no any order that can help us to find given element so each of the elements of array can be given element, so this enforce us to check all the elements in the array.
Note that, lower bound finding an element in unsorted array is Ω(N), because we need check all the elements
Also, because of Array is a static structure, so deletion or insertion is cost-full for us. So for delete in unsorted array you need at the first find it then remove it that has cost O(N).
For deletion in sorted array you can find it in O(logN) and then remove it that has cost O(logN). Note that in this approach, we doesn't shift element of array because this operation is expensive.
I have encountered this problem in an olympiad and im really struggling to find the solution, bc the hint is not really descriptive enough. Please help me.
Thank you!
Well first, we need an array of cumulative sums. Now finding the subarray that we want is just a question of finding the two points no more than k apart whose values have the largest difference.
To solve that second problem we will need a helper array of the minimum cumulative sums within the last k. Or more precisely to hold tuples of (value, position) And now here is pseudocode:
calculate cumulative sums array
initialize best subarray to be first choice
initialize minimum helper array to have just the first choice
for each position in cumulative sums array:
if first in helper array to here is better than best subarray:
update best subarray
while last in minimum helper array >= this value:
pop() last from minimum helper array
insert this at end of minimum helper array
if first in helper array is k before this:
remove first in helper array
This algorithm is O(n). To see that, first note that all array operations on the helper array are amortized O(1). And associated for each position we have at most the following operations (executed slightly out of order):
add value to running total for cumulative sum array
potentially update best subarray discovered so far
be compared with some later element and removed
(that happens on a later loop, but only once for this position)
be compared with an earlier element that is smaller than this
be inserted into helper array
potentially be removed from the start of the helper array.
Every one of those operations are O(1). Since there are n positions, the whole algorithm is O(n).
The last element of the sorted array is replaced with a random value that does not occur in the array. Which classical, ie non-optimized, version of the sorting algorithm should be used to sort this array as efficiently as possible?
Since the array is sorted except for the last element, no sorting is needed.
Simply remove take the last element form the array, and insert it at the right location. Takes O(log n) time to find the location to insert it at.
P.s.
As pointed out by #Henry the actual inserting in an array (at least in most programming-languages) will take another O(n) time because it most likely means to shift all elements one to the right to free the position we want to insert our element.
Problem: You are given an array of n+1 integers from range 1..n. At least one number has duplicate. All array values can be same. Print all duplicates in linear time and constant space. Array can't be modified.
The obvious solution would be to create a bit array with default value false, set 1 in bitarray[array[i]] for each element, then check if it's already 1. That requires additional space, so no good. My another thought: reorder the array by hash and check if a current element and the element array[hash % n] are equal. This is also no good since we can't modify the original array. Now I think that it looks like an impossible task. Is there even a solution to this?
I have an array of structs called struct Test testArray[25].
The Test struct contains a member called int size.
What is the fastest way to get another array of Test structs that contain all from the original excluding the 5 largest, based on the member size? WITHOUT modifying the original array.
NOTE: Amount of items in the array can be much larger, was just using this for testing and the values could be dynamic. Just wanted a slower subset for testing.
I was thinking of making a copy of the original testArray and then sorting that array. Then return an array of Test structs that did not contain the top 5 or bottom 5 (depending on asc or desc).
OR
Iterating through the testArray looking for the largest 5 and then making a copy of the original array excluding the largest 5. This way seems like it would iterate through the array too many times comparing to the array of 5 largest that had been found.
Follow up question:
Here is what i am doing now, let me know what you think?
Considering the number of largest elements i am interested in is going to remain the same, i am iterating through the array and getting the largest element and swapping it to the front of the array. Then i skip the first element and look for the largest after that and swap it into the second index... so on so forth. Until i have the first 5 largest. Then i stop sorting and just copy the sixth index to the end into a new array.
This way, no matter what, i only iterate through the array 5 times. And i do not have to sort the whole thing.
Partial Sorting with a linear time selection algorithm will do this in O(n) time, where sorting would be O(nlogn).
To quote the Partial Sorting page:
The linear-time selection algorithm described above can be used to find the k smallest or the k largest elements in worst-case linear time O(n). To find the k smallest elements, find the kth smallest element using the linear-time median-of-medians selection algorithm. After that, partition the array with the kth smallest element as pivot. The k smallest elements will be the first k elements.
You can find the k largest items in O(n), although making a copy of the array or an array of pointers to each element (smarter) will cost you some time as well, but you have to do that regardless.
If you'd like me to give a complete explanation of the algorithm involved, just comment.
Update:
Regarding your follow up question, which basically suggests iterating over the list five times... that will work. But it iterates over the list more times than you need to. Finding the k largest elements in one pass (using an O(n) selection algorithm) is much better than that. That way you iterate once to make your new array, and once more to do the selection (if you use median-of-medians, you will not need to iterate a third time to remove the five largest items as you can just split the working array into two parts based on where the 5th largest item is), rather than iterating once to make your new array and then an additional five times.
As stated sorting is O(nlogn +5) iterating in O(5n + 5). In the general case finding m largest numbers is O(nlog +m) using the sort algorithm and O(mn +m) in the iteration algoritm. The question of which algorithm is better depends on the values of m and n. For a value of five iterating is better for up to 2 to the 5th numbers I.e. a measly 32. However in terms of operations sorting is more intensive than iterating so it'll be quite a bit more until it is faster.
You can do better theoretically by using a sorted srray of the largest numbers so far and binary search to maintain the order that will give you O(nlogm) but that again depends on the values of n and m.
Maybe an array isn't the best structure for what you want. Specially since you need to sort it every time a new value is added. Maybe a linked list is better, with a sort on insert (which is O(N) on the worst case and O(1) in the best), then just discard the last five elements. Also, you have to consider that just switching a pointer is considerably faster than reallocating the entire array just get another element in there.
Why not an AVL Tree? Traverse time is O(log2N), but you have to consider the time of rebalancing the tree, and if the time spent coding that is worth it.
With usage of min-heap data structure and set heap size to 5, you can traverse the array and insert into heap when the minimum element of heap is less than the element in the array.
getMin takes O(1) time and insertion takes O(log(k)) time where k is the element size of heap (in our case it is 5). So in the worst case we have complexity O(n*log(k)) to find max 5 elements. Another O(n) will take to get the excluded list.