In the worst case while appending an element(inserting at end) array can be full. So a new array is created and n elements are copied from this array to the new array.
I read in literature that worst case time complexity of this operation is O(1), why so? shouldn't it be O(n)?
I did read this question. But did not make any sense to me!
The operation itself is O(n).
If you get the average operations per element, you get O(1), this is the amortized cost.
See more at http://en.wikipedia.org/wiki/Amortized_analysis
I see it the same way that you do.
If it was a List, then it was O(1) to add an element at the end.
But in the case of an array, if it´s full you need to create a new one, copy all the elements in the old array, and then add the new element.
For me it´s O(n) too.
In case of static list/array the time complexity must be O(n), but in case of dynamic array/list, the time complexity comes O(1) because in dynamic array there is a facility to allocate extra memory for the append operation .
Related
Why is array considered a data structure ? How is array a data structure in tetms of efficiency? Please explain by giving some examples
It's a data structure because it's collection of data and the tools to work it.
Primary features:
Extremely fast lookup by index.
Extremely fast index-order traversal.
Minimal memory footprint (not so with the optional modifications I mentioned).
Insertion is normally O(N) because you may need to copy the array when you reallocate the array to make space for new elements. However, you can bring the cost of appending down to amortized O(1) by over-allocating (i.e. by doubling the size of the array every time you reallocate).[1]
Deletion is O(N) because you will need to shift N/2 elements on average. You could keep track the number of unused elements at the start and end of the array to make removals from the ends O(1).[1]
Lookup by index is O(1). It's a simple pointer addition.
Lookup by value is O(N). If the data is ordered, one can use a binary search to reduce this to O(log N).
Keeping track of the first used element and the last used element would technically qualify as a different data structure because the functions to access the data structure are different, but it would still be called an array.
as we know, the time complexity of deleting an array element is o(n), so what is the time complexity of deleting the entire array?
i think is o(1), because the array address space is continuous. is my guess correct?
Deleting the array itself would be O(1) because it would simply release the memory to the pool while deleting every item in the array would be O(n) because each item needs to be removed individually.
There are exceptions, some implementations may for example use an algorithm that clears memory in chunks larger than the size of each item in the array (which would be O(n/c) where c is how many times bigger a chunk is compared to an item in the array), and some languages might simply release the original array and have pointers point to a new empty array which would be O(1). The above answer however is assuming a naive implementation.
I know this is a general question but I really do need to clear my doubt as I am studying about time complexities. I did try to look it up before posting here but found mixed answers.
My question is, when inserting items in an unsorted array considering it is not full the complexity would be O(1) however if it is full it would be O(n) since we would need to copy all the items to a new array. So would we say that the best case complexity of insertion in an array is O(1) and worst case is O(n) or should we say both best and worst case are both O(n)?
Indeed worst case insertion is O(n) if you have to copy the whole array into a larger array. But you must remember, it is the amortize cost we care about.
Think about it this way: how often do I have to copy the whole array ? Once in n times.
So for n-1 I will pay O(1) and for the final insertion O(n).
In total ~2n for n insertions. Average O(1) per op.
Maybe it is easier for you to think about it as O(2).
Now to maintain that, each time the array is filled, twice that size must allocated, so for each item you insert, you pay extra 1 for the time you might need to copy the corresponding item in the first half of the array.
Need to write function for checking repetitive elements in the matrix[1000][1000]. Return True if found any repetitive elements, and False if not.
I think need to make the solution with two steps:
1. Sort every elements in the matrix from smaller to bigger (during sorting we can check the elements on equality) Using merge sort for example.
2. Compare previous and next element one by one from first to last element in the matrix.
Is efficiency of this solution good enough?
This is the element distinctness problem, and it does not seem it is important that your array is 2D, you can regard it as a "regular" array, and solve it with the "regular" solution of element distinctness, which is:
Sort the array, then iterate the elements and check if there is an index i such that arr[i] == arr[i+1].
This solution is O(nlogn) time, assuming efficient sort, with little extra space needed.
Store the elements in a hash-set, and when inserting each element - check if the element already exists in the set.
This solution is O(n) time on average, and O(n^2) time worst case, and needs O(n) extra space.
I have an array of n elements in which only one element is not repeated, else all the other numbers are repeated >1 times. And there is no limit on the range of the numbers in the array.
Some solutions are:
Making use of hash, but that would result in linear time complexity but very poor space complexity
Sorting the list using MergeSort O(nlogn) and then finding the element which doesn't repeat
Is there a better solution?
One general approach is to implement a bucketing technique (of which hashing is such a technique) to distribute the elements into different "buckets" using their identity (say index) and then find the bucket with the smallest size (1 in your case). This problem, I believe, is also known as the minority element problem. There will be as many buckets as there are unique elements in your set.
Doing this by hashing is problematic because of collisions and how your algorithm might handle that. Certain associative array approaches such as tries and extendable hashing don't seem to apply as they are better suited to strings.
One application of the above is to the Union-Find data structure. Your sets will be the buckets and you'll need to call MakeSet() and Find() for each element in your array for a cost of $O(\alpha(n))$ per call, where $\alpha(n)$ is the extremely slow-growing inverse Ackermann function. You can think of it as being effectively a constant.
You'll have to do Union when an element already exist. With some changes to keep track of the set with minimum cardinality, this solution should work. The time complexity of this solution is $O(n\alpha(n))$.
Your problem also appears to be loosely related to the Element Uniqueness problem.
Try a multi-pass scanning if you have strict space limitation.
Say the input has n elements and you can only hold m elements in your memory. If you use a hash-table approach, in the worst case you need to handle n/2 unique numbers so you want m>n/2. In case you don't have that big m, you can partition n elements to k=(max(input)-min(input))/(2m) groups, and go ahead scan the n input elements k times (in the worst case):
1st run: you only hash-get/put/mark/whatever elements with value < min(input)+m*2; because in the range (min(input), min(input)+m*2) there are at most m unique elements and you can handle that. If you are lucky you already find the unique one, otherwise continue.
2nd run: only operate on elements with value in range (min(input)+m*2, min(input)+m*4), and
so on, so forth
In this way, you compromise the time complexity to a O(kn), but you get a space complexity bound of O(m)
Two ideas come to my mind:
A smoothsort may be a better alternative than the cited mergesort for your needs given it's O(1) in memory usage, O(nlogn) in the worst case as the merge sort but O(n) in the best case;
Based on the (reverse) idea of the splay tree, you could make a type of tree that would
push the leafs toward the bottom once they are used (instead of upward as in the splay tree). This would still give you a O(nlogn) implantation of the sort, but the advantage would be the O(1) step of finding the unique element, it would be the root. The sorting algorithm is the sum of O(nlogn) + O(n) and this algorithm would be O(nlogn) + O(1)
Otherwise, as you stated, using a hash based solution (like hash-implemented set) would result in a O(n) algorithm (O(n) to insert and add a counting reference to it and O(n) to traverse your set to find the unique element) but you seemed to dislike the memory usage, though I don't know why. Memory is cheap, these days...