【问题标题】:Is this method O(log N) or constant time?这种方法是 O(log N) 还是恒定时间?
【发布时间】:2014-03-06 06:34:55
【问题描述】:

我有一个将元素插入优先级队列的方法。我想知道它的表演时间

如果插入的元素可以放在队列的底部,我相信它可以是 O(1)。但是,如果要插入的元素是新的最小值并且一直渗透到根,它会在 O(log N) 时间运行。 这个推理正确吗?

这里是方法插入方法:

/**
 * Insert into the priority queue, maintaining heap order.
 * Duplicates are allowed.
 * @param x the item to insert.
 */
public void insert( AnyType x )
{
    if( currentSize == array.length - 1 )
        enlargeArray( array.length * 2 + 1 );

        // Percolate up
    int hole = ++currentSize;
    for( array[ 0 ] = x; x.compareTo( array[ hole / 2 ] ) < 0; hole /= 2 )
        array[ hole ] = array[ hole / 2 ];
    array[ hole ] = x;
}

【问题讨论】:

  • 现在是 O(n),因为 enlargeArray 是 O(n)。
  • @LuiggiMendoza,是的,但仅限于最坏的情况。摊销时间为 O(log N)。
  • @mkrakhin 是的,但 OP 并没有要求摊销时间。

标签: java queue complexity-theory time-complexity priority-queue


【解决方案1】:

在回答您的问题“这个推理是否正确?”时,我会说“不”。通常,O() 符号被视为算法的最坏情况复杂性的指示。有时它可以用于平均情况复杂性,但很少用于最佳情况复杂性。 (请参阅 here 以了解您可能使用它的示例。)您认为算法在最佳情况下是 O(1),但不是在平均或最坏情况下是 O(1)

抛开对enlargeArray() 函数复杂性的担忧(这很可能使这比O(log N) 更多,虽然它的摊销时间不是,但另一方面,无论如何它并不是真正的“算法本身”的一部分因为您总是可以将数组预先分配为“足够大”),我会说您的插入算法是O(log N),因为这既是平均复杂度,也是最坏情况复杂度。

【讨论】:

    【解决方案2】:

    Luiggi 和 mkrakhin 都是正确的:如果您需要扩大数组,则可以使用 zoomArray 调用 O(n),但是由于您不断将数组的大小加倍,从长远来看,它只会发生对数次,所以整个事情将摊销为 O(log N)。

    但是,我认为您要问的真正问题是,如果新元素最小,则此算法是否为 O(1),而答案是“是的,只要您不需要调用放大数组” .看到这一点的方法是注意你会通过你的 for 循环正好 0 次,所以唯一的“完成的工作”是:

    int hole = ++currentSize;
    array[0] = x;
    array[hole] = x;
    

    注意:我认为这似乎也表明了这种情况下的错误(我认为,当您想要交换时,您将相同的元素放在数组的开头和结尾)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-21
      • 1970-01-01
      • 2018-02-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多