【问题标题】:How do I find the time complexity of this algorithm?我如何找到这个算法的时间复杂度?
【发布时间】:2020-10-27 01:06:07
【问题描述】:

我一直在尝试计算这个算法的时间复杂度,但我认为我不正确。

void unknownRuntime( FILE* input )
    {
    int temp;
    int size;
    int n;
    int i=0;
    int *array;

    if( fscanf( input, "%d", &size ) != 1 )
    {
        exit(-1);
    }
    array = (int *) malloc( size*sizeof(int) );
    if( array == NULL )
    {
        exit(-1);
    }

    while( fscanf( input, "%d", &temp ) == 1 && i<size)
    {
        array[i] = temp;
        i++;
    }

    for( i=0; i<size; i++ )
    {
        for( n=size-1; n>1; n/=1.01 )
        {
            array[n-1] = array[n];
        }
    }

    free(array);
}

我开发了一个程序来测试不同的数组大小,以建立输入大小和给定神秘函数的运行时间之间的关系,这是我的结果:

N vs. seconds plot

从我绘制的运行时间来看,它似乎是 O(N log N),但我不确定我是否可以看到算法的位置O(1) 时间将问题规模缩小一小部分。任何帮助将不胜感激。

【问题讨论】:

  • 这是 $n/=1.01$。你可以在到达 1 之前执行 $log_1.01(n)$ 次。

标签: c algorithm time-complexity


【解决方案1】:

让我们看看内部循环。让我们假设我们正在处理实数(而不是类型受限的数字)。

i=0:  n = (size-1)
i=1:  n = (size-1)/1.01
i=2:  n = (size-1)/1.01/1.01
i=3:  n = (size-1)/1.01/1.01/1.01
...

我们可以这样写

n = (size-1) / ( 1.01 ^ i )    // "^" is being used to denote exponentiation.

循环将因此停止

1.01 ^ i >= size - 1

也就是说什么时候

i >= log[1.01](size - 1)       // log[base](x)

因此内循环是O(log N),所以整体是O(N log N)。[1]


现在,以上假设是实数。算法真正在做的是

i=0:  n = (size-1)
i=1:  n = floor( (size-1) / 1.01 )
i=2:  n = floor( floor( (size-1) / 1.01 ) / 1.01 )
i=3:  n = floor( floor( floor( (size-1) / 1.01 ) / 1.01 ) / 1.01 )
...

其中floor 表示隐式转换为int 导致的截断。 (上面未表示的有限浮点精度也可能会出现一些错误。)

n在这个级数中比之前的级数下降得快一点,所以这个级数会更快地接近1,但是差别很小,步数仍然是O(log N)。


  1. log 在计算机科学中通常指的是以 2 为底的对数,但在这里无关紧要,因为我们忽略了 Big-O 表示法中的常数因子,您可以通过乘以常数因子将对数从一个底数转换为另一个底数。

    例如,log[1.01](x) = log[2](x) * 1/log[1.01](2)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多