是否有O(n)算法为正整数数组生成无前缀数组?

时间:2012-03-28 06:51:24

标签: arrays algorithm integer prefix

对于数组[4,3,5,1,2], 我们调用前缀4是NULL,前缀少于4是0;         前缀3为[4],前缀为3为0,因为前缀中没有小于3;         前缀5是[4,3],前缀少于5是2,因为4和3都小于5;         前缀1为[4,3,5],前缀为1为0,因为前缀中没有小于1;         前缀2是[4,3,5,1],前缀少于2是1,因为只有1小于2

因此对于数组[4,3,5,1,2],我们得到[0,0,2,0,1]的无前缀的arrary, 我们可以得到一个O(n)算法来获得无前缀的数组吗?

3 个答案:

答案 0 :(得分:1)

由于comparison sort需要O(n)比较的相同原因,无法在O(n log n)中完成此操作。可能无前缀数组的数量为n!,因此您至少需要log2(n!)位信息才能识别正确的无前缀数组。 log2(n!)O(n log n)Stirling's approximation

答案 1 :(得分:1)

假设输入元素总是固定宽度整数,您可以使用基于基数排序的技术来实现线性时间:

  • L是输入数组
  • X是当前传递的焦点L的索引列表
  • n是我们目前正在处理的事情
  • Count是当前位置左侧第n位的0位数
  • Y是递归的L子序列的索引列表
  • P是零初始化数组,是输出(无前缀数组)

在伪代码中......

Def PrefixLess(L, X, n)
    if (n == 0)
       return;

    // setup prefix less for bit n
    Count = 0

    For I in 1 to |X|
        P(I) += Count
        If (L(X(I))[n] == 0)
            Count++;

    // go through subsequence with bit n-1 with bit(n) = 1
    Y = []
    For I in 1 to |X|
        If (L(X(I))[n] == 1)
            Y.append(X(I))

    PrefixLess(L, Y, n-1)

    // go through subsequence on bit n-1 where bit(n) = 0
    Y = []
    For I in 1 to |X|
        If (L(X(I))[n] == 0)
            Y.append(X(I))

    PrefixLess(L, Y, n-1)

    return P

然后执行:

PrefixLess(L, 1..|L|, 32)

答案 2 :(得分:0)

我认为这应该有用,但请仔细检查细节。让我们在原始数组a [i]中调用一个元素,在前缀数组中调用一个元素作为p [i],其中i是各个数组的第i个元素。

所以,假设我们在[i],我们已经计算了p [i]的值。有三种可能的情况。如果a [i] == a [i + 1],则p [i] == p [i + 1]。如果a [i]< a [i + 1],然后p [i + 1]> = p [i] + 1.这使我们得到a [i]>的情况。一个[I + 1]。在这种情况下,我们知道p [i + 1]> = p [i]。

在天真的情况下,我们返回前缀并开始计算小于a [i]的项目。但是,我们可以做得更好。首先,认识到p [i]的最小值为0,最大值为i。接下来看一下索引j的情况,其中i>学家如果a [i]> = a [j],则p [i]> = p [j]。如果a [i]< a [j],然后p [i]< = p [j] + j。因此,我们可以通过p更新p [i] _min和p [i] _max的值来开始倒退。如果p [i] _min等于p [i] _max,那么我们就有了解决方案。

对算法进行包络分析,它具有O(n)最佳案例性能。这是列表已经排序的情况。最糟糕的情况是它被反向排序。然后性能是O(n ^ 2)。平均性能将是O(k * n),其中k是需要回溯多少。我的猜测是随机分布的整数,k会很小。

我也很确定如何针对部分排序数据的情况优化此算法。我会看Timsort对如何做到这一点的一些启发。它使用运行检测来检测部分排序的数据。因此算法的基本思想是通过列表一次并查找数据运行。对于递增的数据运行,您将得到p [i + 1] = p [i] +1的情况。对于下行运行,p [i] = p_run [0]其中p_run是运行中的第一个元素。