查找数组是否为O(n)时间和O(1)空间中的序列

时间:2013-08-07 10:50:34

标签: algorithm language-agnostic

给定一个可能包含重复项的数组,我们如何才能找到它是否是一个序列?

EG。 {7, 3, 5, 4, 6, 2}

是序列2, 3, 4, 5, 6, 7

排序是一个明显的解决方案。我们如何在O(n)时间和O(1)空间中做到这一点?

3 个答案:

答案 0 :(得分:10)

假设1,2,3,3,4,1是有效的未排序序列,2,4,6,8也是有效序列(第2步),但1,3,5,9不是(7缺失)并假设输入数组可以被覆盖,

  1. 确定最大值和最小值:O(n)时间,O(1)空间。您可以使用数组的第一个和最后一个位置。
  2. 确定步骤。该步骤是所有a_n - min
  3. 中最不常见的乘数
  4. 如果他们相距太远(max - min > (count + 1) * step),这不是一个序列。否则,
  5. 进行就地整数排序。直到开始>结束:
    • 看第一个位置。设值为v_0
    • 当我们假设没有重复项((v_0 - min) / step + start)为i时,让它的目标位置
      • 如果目标位置小于start,则为重复。将其移至后面并减少结束指针
      • 如果目标位置超过end,则序列中缺少某些元素。声明数组不是序列。
    • 如果元素位于目标位置,则递增开始指针和min引用
    • 如果目标位置的元素小于参考最小值或等于v_0,则将其交换到数组的末尾并递减结束指针。这是重复的。
    • else将目标位置的元素与v_0交换。
  6. 声明数组序列
  7. 就地整数排序是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)

试试看:

  1. 确定最小值和最大值 - O(n)
  2. 创建一个可以为原始数组大小的可空值的数组 - O(n)(是的,此处缺少空格要求)
  3. 迭代原始数组(O(n))并将你找到的数字放在索引处(数字 - 分钟),如果你在那里找到一个值,你就没有序列,如果你结束了没有声明位置,你有序列
  4. 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;
    }