给定一个可能包含重复项的数组,我们如何才能找到它是否是一个序列?
EG。 {7, 3, 5, 4, 6, 2}
是序列2, 3, 4, 5, 6, 7
排序是一个明显的解决方案。我们如何在O(n)时间和O(1)空间中做到这一点?
答案 0 :(得分:10)
假设1,2,3,3,4,1
是有效的未排序序列,2,4,6,8
也是有效序列(第2步),但1,3,5,9
不是(7缺失)并假设输入数组可以被覆盖,
a_n - min
max - min > (count + 1) * step
),这不是一个序列。否则,v_0
(v_0 - min) / step + start
)为i
时,让它的目标位置
start
,则为重复。将其移至后面并减少结束指针end
,则序列中缺少某些元素。声明数组不是序列。min
引用v_0
,则将其交换到数组的末尾并递减结束指针。这是重复的。v_0
交换。就地整数排序是O(n)。在每一步中它都是:
在排序结束时,每个元素在重复块中都是重复的,或者在排序块中的正确位置。
请注意,可以省略步骤#3。 #4将正确地确定这不是一个序列,虽然速度较慢。
如果步骤必须为1,则可以稍微简化此算法(参见修订版#1)
答案 1 :(得分:1)
此算法(Python)会破坏原始数组,但会满足O(n)时间和O(1)额外空间。
# 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
我还没有正式证明它有效。
为什么这是O(n)?在最后的双循环中,在元素首次被放入其正确的位置后,它只能被再次访问 - 在另一个内部循环的开始处,在那里看到它位于正确的位置,或者在它被发现的位置妨碍重复元素(if t == h
部分)。
答案 2 :(得分:-1)
试试看:
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;
}