扫描有界长度字符串的复杂性。 O(n) 还是 O(1)?

Complexity of scanning a bounded length string. O(n) or O(1)?

假设我们有一串 唯一的 ASCII 字符,这意味着它的长度永远不会超过 128 个字符。

如果我要扫描这个字符串,其中 扫描 意味着对每个字符执行 constant-time 操作,这次扫描算不算作为 O(n) 或 O(1)?

其中n是字符串的实际长度。

一方面它是 O(n),因为程序的复杂性取决于某个变量 n,它可以在 [0, 128] 范围内改变宽度。

另一方面,如果程序总是进行相同数量的操作,那么您的复杂度为 O(1)。事实并非如此,因为如果它的长度更大,则需要更多的工作。

尽管考虑到最坏的情况是 O(128) 因此使其成为 O(1)

答案

当根据 n 询问算法的时间或 space 复杂度时,您需要定义 n 是什么。

如您所知,n 个字符数组的线性扫描具有 O(n) 的时间复杂度。由于您将相同的算法应用于 <= 128 个字符的数组,因此您可以肯定地说您正在对数组应用 O(n) 算法。

但是,如果你将算法定义为"scanning through a character array of max 128 characters",那么你的算法确实会有O(1)的时间复杂度,因为它的操作数上限是一个常数。

所以回答你的问题:这是一个角度问题。你如何定义你的算法?

  • "A generalized scan of an array of length n"?然后是 O(n),其中 n 在您的特定应用程序中恰好不会超过 128(对您有好处)。
  • "A scan of 128 or fewer characters"?然后是O(1),因为它的时间上限是一个常数。

进一步思考

现在,即使您要扩展数组的长度以填满所有 RAM,无论多大,它仍然是一个有限整数,因此从数学上讲,您声称它将 运行 在 O(1) 时间内。 但是!定义一个算法来扫描适合您的 RAM 的数组有多重要?我们刚刚严重削弱了我们算法的实用性,因为如果,比方说,我的 RAM 比你多,那么你的算法将无法满足我的需求。

这就是为什么我们使用参数 n 来表示一些度量(这里是数组的长度)。这 允许 我们定义一个适用于任何(!)大小输入的扫描算法。如您所知,此算法充其量是 O(n),听起来可能不如 O(1),但它现在是一种通用算法,可用于任何输入大小,而不是我们使用的算法将输入限制作为算法本身的一部分。