一次性算法(需要说明) 为啥空间复杂度为 O(1)?

Posted

技术标签:

【中文标题】一次性算法(需要说明) 为啥空间复杂度为 O(1)?【英文标题】:One-pass algorithm (clarification needed) Why the space complexity is O(1)?一次性算法(需要说明) 为什么空间复杂度为 O(1)? 【发布时间】:2019-12-06 03:08:09 【问题描述】:

来自en.wikipedia:

一次性算法通常需要 O(n)(参见“大 O”表示法)时间并且少于 O(n) 存储(通常为 O(1)),其中 n 是输入的大小。

我用 xdebug.profiler_enable=1 做了一个测试:

function onePassAlgorithm(array $inputArray): int

    $size = count($inputArray);
    for ($countElements = 0; $countElements < $size; ++$countElements) 
    

    return $countElements;


$range = range(1, 1_000_000);
$result = onePassAlgorithm($range);

这段代码在qcachegrind中的内存使用量为:33 558 608字节,并且全部100%被range()函数使用。 这部分在我看来没问题,因为在 onePassAlgorithm 函数中我们只有两个 int 变量。 这就是 空间复杂度 为 O(1) 的原因。

然后我又做了一个测试:

function onePassAlgorithm(array $inputArray, int $twoSum): array

    $seen_nums = [];
    foreach ($inputArray as $key => $num) 
        $complement = $twoSum - $num;
        if (isset($seen_nums[$complement])) 
            return [$seen_nums[$complement], $key];
        
        $seen_nums[$num] = $key;
    

    return [];


$range = range(1, 1_000_000);
$result = onePassAlgorithm($range, 1_999_999);

在 qcachegrind 中我们可以看到 onePassAlogorithm 函数只使用了 376 个字节(返回语句的大小)。我们不需要更多的顺序保存在 $seen_nums 变量中吗?那么空间复杂度又是O(1)?

我的问题是:为什么 qcachegrind 显示我们复制整个 $inputArray 的变量 $seen_nums 不消耗内存?

或者换句话说为什么我第二次实现这个算法的存储复杂度是O(1)?

【问题讨论】:

大概第一个更快,因为它在循环中不做任何事情? @greybeard 是 $inputArray,重命名了。 也许 qcachegrind 并没有告诉你你认为它在告诉你什么。 【参考方案1】:

来自 Xdebug 文档:

[2007-05-17] — 删除了对内存分析的支持,因为它不能正常工作。

[2015-02-22] — Xdebug 2.3.0 为普通跟踪文件中的函数返回添加了时间索引和内存使用情况。

所以我感到困惑的原因是 xdebug 配置文件只显示了函数返回的内存使用情况,而不是我预期的完整内存配置文件。

【讨论】:

以上是关于一次性算法(需要说明) 为啥空间复杂度为 O(1)?的主要内容,如果未能解决你的问题,请参考以下文章

马士兵LeetCode算法讲解

为啥中位数算法被描述为使用 O(1) 辅助空间?

关于描述算法复杂度的一些说明

为啥基数排序的空间复杂度为 O(k + n)?

算法:排序

排序算法时间复杂度为O(n²)的排序算法