Given an array which might contain duplicates, How can we find if it is a sequence?
Eg. {7, 3, 5, 4, 6, 2}
is a sequence 2, 3, 4, 5, 6, 7
Sorting is an obvious solution. How can we do this in O(n) time and O(1) space?
Explanation: Duplicate element in the array are 1 , 3 and 6 Input: n = 6, array = {5, 3, 1, 3, 5, 5} Output: 3 and 5. Explanation: Duplicate element in the array are 3 and 6 Duplicates in an array in O (n) and by using O (1) extra space | Set-2 .
Input : n = 7 and array [] = {1, 2, 3, 6, 3, 6, 1} Output: 1, 3, 6 Explanation: The numbers 1 , 3 and 6 appears more than once in the array. Input : n = 5 and array [] = {1, 2, 3, 4 ,3} Output: 3 Explanation: The number 3 appears more than once in the array.
The frequency can be retrieved by dividing the a % n’th element by n. Traverse the given array from start to end. For every element in the array increment the arr [i]%n‘th element by n.
There is an algorithm known to find smallest element in an unordered array of n elements. We can use the algorithm to find the median as well since median will be smallest element if is odd, and average of and smallest element when is even. The algorithm is based on a divide and conquer strategy.
assuming 1,2,3,3,4,1
is a valid unsorted sequence and 2,4,6,8
is a valid sequence (of step two) as well, but 1,3,5,9
isn't (7 is missing) and assuming the input array can be overwritten,
a_n - min
max - min > (count + 1) * step
), this cannot be a sequence. Otherwise,v_0
(v_0 - min) / step + start
) be i
start
, it's a duplicate. Move it to the back and decrement the end pointerend
, some element is missing in the sequence. Claim the array is not a sequence.min
referencev_0
, swap it to the end of the array and decrement the end pointer. It's a duplicate.v_0
.The in-place integer sort is O(n). In each step it either:
At the end of sorting, each element is either a duplicate in the duplicate block, or at its correct position in the sorted block.
Note that step #3 can be left out. #4 will correctly determine this is not a sequence, albeit slower.
If the step has to be 1, then this algorithm can be simplified somewhat (see revision #1)
This algorithm (Python) destroys the original array, but otherwise satisfies O(n) time and O(1) extra space.
# INPUT: An array 'arr' of N integers.
# OUTPUT: If the array consists exactly of the integers
# S, S+1, ..., S+N-1, for some S, in any order,
# then modifies 'arr' into a sorted array and returns it.
# Otherwise, returns False, and 'arr' may have been modified.
def sort_sequence (arr):
the_min = min(arr)
the_max = max(arr)
if the_max - the_min != len(arr) - 1:
return False
for i in range(len(arr)):
arr[i] -= the_min
for i in range(len(arr)):
while arr[i] != i:
j = arr[i]
t = arr[j]
if t == j:
return False
arr[j] = j
arr[i] = t
for i in range(len(arr)):
arr[i] += the_min
return arr
I have not formally proven that it works yet.
Why is this O(n)? In the final double loop, after an element is first put into its correct spot, it can only be visited one more time - either at the beginning of another inner loop where it is seen to be in the right spot, or where it is found to be in the way of a duplicate element (the if t == h
part).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With