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?
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?
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).
Let my try:
public bool IsSequence(int[] values)
{
var min = values[0];
var max = values[0];
foreach (var value in values)
{
min = min > value ? value : min;
max = max > value ? max : value;
}
if ((max - min + 1) != values.Length)
return false;
var testingArray = new int?[values.Length];
foreach (var value in values)
{
var index = value - min;
if (testingArray[index].HasValue)
return false;
else
testingArray[index] = value;
}
return true;
}