We have one unsorted array with distinct entries a_1, a_2, ... a_n, and we also know a shifted array a_(n-k), ...a_n, a_1, a_2, ... The goal is to find the displacement k given these two arrays. Of course there is a worst case linear algorithm O(n). But can we do better than this?
There is a hint that the answer has something to do with the k distribution. If k is distributed uniformly between 0 and n, then we have to do it within O(n). If k is distributed in otherway there might be some better way.
If there are no duplicates in the array (distinct entries) I would do this with a while loop and incrementing an index value k starting from 0 and comparing two items at once one from the beginning and one from the end. Such as array1[k] === array2[0] or array1[n-k] === array[0] and the index value k should be the displacement once the above comparison returns true.
There is an O(sqrt(n)) solution, as the op figured out based on #greybeard's hint.
From the first list, hash the first sqrt(n) elements. For the second list, look at the elements advancing by sqrt(n) elements at each time.
However, we might ask if there is a solution that might be close to O(k) (or less!) if k is small and n is large. In fact, I claim there is an O(sqrt(k)) solution.
For that, I propose an incremental process of increasing the step size. So the algorithm looks like this:
First, grab 2 elements from the first list - hash those values (and keep position of values as lookup value, so this should be thought of as a HashMap with key being elements of the list and values being positions).
Compare those elements with the first and third element from the second list.
Hash the values from the second list as well.
Next, look at the third element from the first list - hashing the value. In the process, see if it matches either of the elements found in the second list. Next, advance 3 elements in the second list, and compare its value - remember that values as well.
Continue like this:
increase the prefix length from the first list, and at each point, increasing the step size of the second list. Whenever you grab a new element for the first list, you have to compare it with values in the second list, but that's fine because it does not significantly affect performance.
Notice that when your prefix length is p, you have already checked the first p*(p+1)/2 elements in the second list. So for a given value of k, this process will require that prefix length p is approximately sqrt(2k), which is O(sqrt(k)) as required.
Basically, if we know that a[0] does not equal b[0], we do not need to check if a[1] equals b[1]. Extending this idea and hashing the a's, checks can go as follows:
a[0] == b[0] or b[0] in hash? => known k's: 0
a[1] == b[2] or b[2] in hash? => known k's: 0,1,2
a[2] == b[5] or b[5] in hash? => known k's: 0,1,2,3,4,5
a[3] == b[9] or b[9] in hash? => known k's: 0,1,2,3,4,5,6,7,8,9
a[4] == b[14] or b[14] in hash? => known k's: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14
...
(I think that's O(sqrt n) time and space worst case complexity.)
maybe if you incorporate them into a hashtable. then the access and compare time for a(n-k) in the original array will be O(1).
Related
In an unsorted array, an element is a local maximum if it is larger than
both of the two adjacent elements. The first and last elements of the array are considered local
maxima if they are larger than the only adjacent element. If we create an array by randomly
permuting the numbers from 1 to n, what is the expected number of local maxima? Prove
your answer correct using additivity of expectations.
Im stuck with this question, i have no clue how to solve this...
You've got an unsorted Array array with n elements. You've got two possible positions for where the local maxima could be. The local maxima could be either on the end or between the first and last element.
Case 1:
If you're looking at the element in either the first or last index (array[0] or array[n-1]) What's the probability that the element is a local maxima? In other words what's the probability that the value of that element will be greater than the element to its right? There are 10 possible value each index could hold {0,1,2,3,4,5,6,7,8,9}. Therefore a 50% chance that on average the element in the first index will be greater than the element in the second index. (array[0] > array[1])
Case 2:
If you're looking at any element that ISNT the first or last element of the array, (n-2 elements) then what's the probability that each one will be the local max? Similarly to the first case, we know there are 10 possible values each index could hold, therefore a 1/3 chance that on average, the element we choose will be greater than the one before it and greater than the one after it.
Putting it all together:
There are 2 cases that have a 1/2 probability of being local maxima and there are n-2 cases that have a 1/3 probability of being local maxima. (2 + n-2 = n, all possible cases). (2)(1/2) + (n-2)(1/3) = (1+n)/(3).
Solvable of course, but won't deprive you the fun of doing it yourself. I will give you a tip. Consider this sketch. What do you think it represents? If you figure this out, you will know that a pattern is available to discover for any n, odd and even. Good luck. If still stuck, will tip you more.
So, I have an array containing integers. I need to sort it. However, the only operation I can perform is a unit shift. That is, I can move the last element of the sequence to its beginning.
`a1, a2, ..., an → an, a1, a2, ..., an - 1.`
what is the minimum number of operations that I need to sort the sequence?
The number of integers in the array can be upto 10^5. And each integer individual value can be 10^5 too. Also, if array is already sorted, print 0 else if array cannot be sorted by unit shifts, print -1.
The solution that I thought of:
Check if array is sorted or not.
If array is sorted, print 0 else
Set count = 0
Rotate array by one unit and increment count.
Check if array is sorted: if yes, print count and break, else
repeat steps 4-5 till count < (total integers in array).
Now, the above solution has a time complexity of O(n^2). Because, I am checking for each individual element if array is sorted and this checking takes O(n) time, and I have n elements, so that makes it O(n^2).
Can anyone suggest me some other better approach?
Thanks!
PS: I tried really hard thinking of some other approach. I reached uptill counting inversions, but that doesn't really help.
Just iterate the array, find the first index i such that arr[i] > arr[i+1] (If there is no such index, we are done since array is already sorted), then check if arr[i+1],...,arr[n] is sorted, and if arr[n] <= arr[1]. If it is, it can be done by doing n-i rotations.
Otherwise, there is no solution.
Time complexity is O(n), space complexity O(1).
Appendix: Correctness of the algorithm:
Claim 1:
If the array cannot be splitted to two arrays
arr[1],arr[2],..,arr[i] and arr[i+1],...,arr[n] - both sorted,
then there is no solution.
Proof:
Let's assume i is the first index where arr[i] > arr[i+1], and let j be some other index such that arr[j] > arr[j+1], j!=i. There must be such because arr[i+1],...,arr[n] is unsorted.
By definition, while j+1 was not "unit shifted", the array is unsorted.
Immidiately after it was shifted, it is still not sorted since arr[i] > arr[i+1], and after another shift, arr[j] is again before arr[j+1], and violating the sorted order.
Thus, the array cannot be sorted.
Claim 2:
Assume an array that can be splitted to two sorted array
arr[1],...,arr[i], and arr[i+1],...,arr[n]. Also assume
arr[i] > arr[i+1]. Then, the array can be "unit shifted" into
sorted one, if and only if arr[n] <= arr[1].
Proof:
<---
The array is not sorted, so at least one unit shift must be done. This unit shift places arr[n] before arr[1], and the array will never be sorted unless arr[n]<=arr[1]
--->
Assume arr[n]<=arr[1], then by shifting arr[i+1],...,arr[n], we get the following array:
arr[i+1],arr[i+2],...,arr[n],arr[1],arr[2],...,arr[i]
Note that arr[i+1]<= arr[i+2] <= .... <= arr[n] since we assumed it is sorted.
Similarly arr[1]<=arr[2]<=...<=arr[i]
Also note arr[n] <= arr[i], from assumption.
By joining the 3 above inequalities we get:
arr[i+1] <= arr[i+2] <= ... <= arr[n] M= arr[1] <= arr[2] <= ... <= arr[i]
The above is by definition a sorted array, which concludes the proof for the claim.
Claim 3:
The algorithm is correct
By applying claim1,claim2 and handling specifically the case where array is already sorted, we get that:
The array can be sorted using "unit shifts" if and only if: It is already sorted, OR conditions of claim2 applies, and this concludes the proof.
QED
I have been given an array (of n elements) and i have to find the smallest element on the right side of each element which is greater than itself(current element).
For example :
Array = {8,20,9,6,15,31}
Output Array = {9,31,15,15,31,-1}
Is it possible to solve this in O(n).? I thought of traversing the array from the right side (starting from n-2) and building a balance binary search tree for the remaining elements, as searching in it for an element which is immediately greater than the current element would be O(logn) .
Hence time complexity would come out to be O(n*(log(n)).
Is there a better approach to this problem?
The problem you present is impossible to solve in O(n) time, since you can reduce sorting to it and thereby achieve sorting in O(n) time.
Say there exists an algorithm which solves the problem in O(n).
Let there be an element a.
The algorithm can also be used to find the smallest element to the left of and larger than a (by reversing the array before running the algorithm).
It can also be used to find the largest element to the right (or left) of and smaller than a (by negating the elements before running the algorithm).
So, after running the algorithm four times (in linear time), you know which elements should be to the right and to the left of each element. In order to construct the sorted array in linear time, you'd need to keep the indices of the elements instead of the values. You first find the smallest element by following your "larger-than pointers" in linear time, and then make another pass in the other direction to actually build the array.
Others have proved that it is impossible in general to solve in O(n).
However, it is possible to do in O(m) where m is the size of your largest element.
This means that in certain cases (e.g. if if your input array is known to be a permutation of the integers 1 up to n) then it is possible to do in O(n).
The code below shows the approach, built upon a standard method for computing the next greater element. (There is a good explanation of this method on geeks for geeks)
def next_greater_element(A):
"""Return an array of indices to the next strictly greater element, -1 if none exists"""
i=0
NGE=[-1]*len(A)
stack=[]
while i<len(A)-1:
stack.append(i)
while stack and A[stack[-1]]<A[i+1]:
x=stack.pop()
NGE[x]=i+1
i+=1
return NGE
def smallest_greater_element(A):
"""Return an array of smallest element on right side of each element"""
top = max(A) + 1
M = [-1] * top # M will contain the index of each element sorted by rank
for i,a in enumerate(A):
M[a] = i
N = next_greater_element(M) # N contains an index to the next element with higher value (-1 if none)
return [N[a] for a in A]
A=[8,20,9,6,15,31]
print smallest_greater_element(A)
The idea is to find the next element in size order with greater index. This next element will therefore be the smallest one appearing to the right.
This cannot be done in O(n), since we can reduce Element Distinctness Problem (which is known to be sovleable in Omega(nlogn) when comparisons based) to it.
First, let's do a little expansion to the problem, that does not influence its hardness:
I have been given an array (of n elements) and i have to find the
smallest element on the right side of each element which is greater/equals
than itself(current element).
The addition is we allow the element to be equal to it (and to the right), and not only strictly greater than1.
Now, Given an instance of element distinctness arr, run the algorithm for this problem, and look if there is any element i such that arr[i] == res[i], if there isn't answer "all distinct", otherwise: "not all distinct".
However, since Element Distinctness is Omega(nlogn) comparisons based, it makes this problem such as well.
(1)
One possible justification why adding equality is not making the problem more difficult is - assuming elements are integers, we can just add i/(n+1) to each element in the array, now for each two elements if arr[i] < arr[j], also arr[i] + i/(n+1) < arr[j] + j/(n+1), but if arr[i] = arr[j], then if i<j arr[i] + i/(n+1) < arr[j] + j/(n+1), and we can have the same algorithm solve the problem for equalities as well.
I have an array
A[4]={4,5,9,1}
I need it would give the first 3 top elements like 9,5,4
I know how to find the max element but how to find the 2nd and 3rd max?
i.e if
max=A[0]
for(i=1;i<4;i++)
{
if (A[i]>max)
{
max=A[i];
location=i+1;
}
}
actually sorting will not be suitable for my application because,
the position number is also important for me i.e. I have to know in which positions the first 3 maximum is occurring, here it is in 0th,1th and 2nd position...so I am thinking of a logic
that after getting the max value if I could put 0 at that location and could apply the same steps for that new array i.e.{4,5,0,1}
But I am bit confused how to put my logic in code
Consider using the technique employed in the Python standard library. It uses an underlying heap data structure:
def nlargest(n, iterable):
"""Find the n largest elements in a dataset.
Equivalent to: sorted(iterable, reverse=True)[:n]
"""
if n < 0:
return []
it = iter(iterable)
result = list(islice(it, n))
if not result:
return result
heapify(result)
for elem in it:
heappushpop(result, elem)
result.sort(reverse=True)
return result
The steps are:
Make an n length fixed array to hold the results.
Populate the array with the first n elements of the input.
Transform the array into a minheap.
Loop over remaining inputs, replacing the top element of the heap if new data element is larger.
If needed, sort the final n elements.
The heap approach is memory efficient (not requiring more memory than the target output) and typically has a very low number of comparisons (see this comparative analysis).
You can use the selection algorithm
Also to mention that the complexity will be O(n) ie, O(n) for selection and O(n) for iterating, so the total is also O(n)
What your essentially asking is equivalent to sorting your array in descending order. The fastest way to do this is using heapsort or quicksort depending on the size of your array.
Once your array is sorted your largest number will be at index 0, your second largest will be at index 1, ...., in general your nth largest will be at index n-1
you can follw this procedure,
1. Add the n elements to another array B[n];
2. Sort the array B[n]
3. Then for each element in A[n...m] check,
A[k]>B[0]
if so then number A[k] is among n large elements so,
search for proper position for A[k] in B[n] and replace and move the numbers on left in B[n] so that B[n] contains n large elements.
4. Repeat this for all elements in A[m].
At the end B[n] will have the n largest elements.
I have an array A = [a1, a2, a3, a4, a5...] and I want to find two elements of the array, say A[i] and A[j] such that i is less than j and A[j]-A[i] is minimal and positive.
The runtime has to be O(nlog(n)).
Would this code do the job:
First sort the array and keep track of the original index of each element (ie : the index of the element in the ORIGINAL (unsorted) array.
Go through the sorted array and calculate the differences between any two successive elements that verify the initial condition that the Original Index of the bigger element is bigger than the original index of the smaller element.
The answer would be the minimum value of all these differences.
Here is how this would work on an example:
A = [0, -5, 10, 1]
In this case the result should be 1 coming from the difference between A[3] and A[0].
sort A : newA=[-5,0,1,10]
since OriginalIndex(-5)>OriginalIndex(0), do not compute the difference
since OriginalIndex(1)>OriginalIndex(0), we compute the difference = 1
since OriginalIndex(10)>OriginalIndex(1), we compute the difference = 9
The result is the minimal difference, which is 1.
Contrary to the claim made in the other post there wouldn't be any problem regarding the runtime of your algorithm. Using heapsort for example the array could be sorted in O(n log n) as given as an upper bound in your question. An additional O (n) running once along the sorted array couldn't harm this any more, so you would still stay with runtime O (n log n).
Unfortunately your answer still doesn't seem to be correct as it doesn't give the correct result.
Taking a closer look at the example given you should be able to verify that yourself. The array given in your example was: A=[0,-5,10,1]
Counting from 0 choosing indices i=2 and j=3 meets the given requirement i < j as 2 < 3. Calculating the difference A[j] - A[i] which with the chosen values comes down to A[3] - A[2] calculates to 1 - 10 = -9 which is surely less than the minimal value of 1 calculated in the example application of your algorithm.
Since you're minimising the distance between elements, they must be next to each other in the sorted list (if they weren't then the element in between would be a shorter distance to one of them -> contradiction). Your algorithm runs in O(nlogn) as specified so it looks fine to me.