【问题标题】:Time Complexity of a nested for loop that parses a matrix解析矩阵的嵌套 for 循环的时间复杂度
【发布时间】:2012-04-27 04:44:24
【问题描述】:

假设我有一个包含 X 行和 Y 列的矩阵。元素的总数是 X*Y,对吗?那么这会使 n=X*Y 吗?

for (i=0; i<X; i++)
{
   for (j=0; j<Y; j++)
   {
      print(matrix[i][j]);
   }
}

那不是说这个嵌套的for循环是O(n)吗?还是我误解了时间复杂度的工作原理?

一般来说,我认为所有嵌套的 for 循环都是 O(n^2),但是如果它通过 X*Y 调用 print(),这不意味着时间复杂度是 O(X*Y) 并且X*Y 等于 n?

【问题讨论】:

    标签: time for-loop matrix nested complexity-theory


    【解决方案1】:

    如果你有一个大小为 rows*columns 的矩阵,那么内部循环(假设)是 O(columns),嵌套循环一起是 O(rows*columns)。

    您将 N 的问题大小与 N^2 的问题大小混淆了。您可以说您的矩阵大小为 N 或您的矩阵大小为 N^2,但除非您的矩阵是正方形,否则您应该说您有一个大小为 Rows*Columns 的矩阵。

    【讨论】:

      【解决方案2】:

      你说n = X x Y 是对的,但你说嵌套循环应该是O(n) 是错误的。如果您干运行代码,就可以理解嵌套循环的含义。您会注意到,对于外循环的每次迭代,内循环都会运行n(或大小条件)次。因此,通过简单的数学运算,您可以推断出它的O(n^2)。但是,如果您在迭代 (X x Y) 时只有一个循环(例如:for(i = 0; i&lt;(X*Y); i++) 元素,那么它将是 O(n),因为您不会在任何时候重新开始迭代。 希望这是有道理的。

      【讨论】:

        【解决方案3】:

        这个答案写得仓促,收到了一些反对意见,所以我决定澄清并重写它

        算法的时间复杂度是根据算法要解决的问题的大小来表示算法的运算次数。

        这里涉及两种尺寸。

        1. 第一个大小是矩阵 X × Y 的元素数,这对应于复杂性理论中所谓的输入大小。令 k = X × Y 表示矩阵中元素的数量。由于双循环中的操作数是 X × Y,所以在 O(k) 内。

        2. 第二个大小是矩阵的列数和行数。设 m = max(X,Y)。双循环中的操作数为 O(m^2)。通常在线性代数中,这种大小用于表征 m × m 矩阵上的矩阵运算的复杂度。

        当您谈论复杂性时,您必须准确指定如何对实例问题进行编码以及使用什么参数来指定其大小。在复杂性理论中,我们通常假设算法的输入是来自某个有限字母表的字符串,并根据上操作数的上限来衡量算法的复杂性。由长度为 n 的字符串给出的问题实例。在复杂性理论中,n 通常是输入的大小

        在算法的实际复杂性分析中,我们经常使用在特定上下文中更有意义的实例大小的其他度量。例如,如果A 是图的连接矩阵,我们可以使用顶点数量V 作为问题实例复杂度的度量,或者如果A 是作用于的线性算子的矩阵向量空间,我们可以使用向量空间的维度作为这样的度量。对于 square 矩阵,约定是根据矩阵的维数来指定复杂度,即用 n 来衡量作用于 n × n 矩阵的算法的复杂度。它通常具有实际意义,也符合特定应用领域的惯例,即使它可能与复杂性理论的惯例相矛盾。

        让我们将名称 Matrix Scan 赋予我们的双循环。您可以合理地说,如果 Matrix Scan 实例的大小是矩阵的字符串编码的长度。假设条目的大小有界,它是矩阵中元素的数量 k。那么我们可以说Matrix Scan的复杂度在O(k)之内。另一方面,如果我们将 m = max(X,Y) 作为表征实例复杂度的参数,这在许多应用程序中是惯用的,那么 X×Y 的复杂度矩阵扫描矩阵也将在 O(m^2) 中。对于方阵 X = Y = m 和 O(k) = O(m^2)。

        注意: cmets 中的一些人问我们是否总能找到问题的编码以将 any 多项式问题简化为线性问题。这不是真的。对于某些算法,操作数量的增长速度快于其输入的字符串编码长度。例如,没有算法可以将两个 m×m 矩阵与 θ(m^2) 次运算相乘。这里输入的大小增长为 m^2,但是Ran Raz 证明操作的数量增长至少与 m^2 log m 一样快。如果 n 在 O(m^2) 中,则 m^2 log m 在 O(n log n) 中,并且最著名的算法复杂度随着 O(m^(2+c)) = O(n^(1+ c/2)),其中对于 Coppersmith-Winograd 算法的版本,c 至少为 0.372,对于常见的迭代算法,c = 1。

        【讨论】:

        • 如何扣除O(m^2) = O(n)?这显然是错误的!它会像我们将每个多项式问题放到线性空间中那样工作吗:)
        • 你说:In general let m = max(X,Y) then O(m^2) = O(n)。无论您如何使用它,这都是公然错误的。但是O(X*Y)=O(n^2) 是完全有效的,你不需要n=max(X,Y),因为它是大 O 而不是大 Theta 符号并且它是隐含的。你现在得到答案的方式,你声称“嵌套循环是 O(n)”,如果你写了一篇论文并证明你是诺贝尔奖的:)
        • 为了澄清 OP 和其他任何人,O(X*Y)O(n^2),因为 X 和 Y 是变量。 O(X*Y) 可以是 O(n) 只有当 X 或 Y 是一个常数(无论多大),因为它不会增长。最后 O(X*Y) 可以是 O(1) 只有当 X 和 Y 是常量时,函数不能增长并且需要相同的时间来执行。
        • 老实说,就大 O 表示法而言,它就像 1+1=2 一样简单:嵌套循环是 O(n^2),因为您在 N 次迭代中重复了 N 次迭代,即 N^2 在全部的。而且 O(n^2) 不能像你所拥有的那样等于 O(n),这在数学和逻辑上都是荒谬的,你不能认识到吗?如果是这种情况,那么就不会有多项式空间,因为每个问题都可以“放松”为线性问题。因此,请自己尝试一些数字或查看this。第一个示例中的 O(n) 演化为 NON 嵌套循环。
        • 您是否尝试过真正测试您的代码?原因I did and guess what.
        【解决方案4】:

        一般来说,我认为所有嵌套的 for 循环都是 O(n^2),

        你错了。我猜让你感到困惑的是,人们经常使用方形(X==Y)矩阵作为示例,因此复杂度为 n*n(X==n,Y==n)。

        如果你想练习你的 O(*) 技巧,试着弄清楚为什么矩阵乘法是 O(n^3)。如果您不知道矩阵乘法的算法,很容易在网上找到它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-05-18
          • 1970-01-01
          • 2021-02-15
          • 2022-01-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多