这个算法的时间复杂度是多少

Posted

技术标签:

【中文标题】这个算法的时间复杂度是多少【英文标题】:What will be the time complexity of this algorithm 【发布时间】:2020-08-03 09:53:18 【问题描述】:

我对竞争性编程和大 O 表示法非常陌生。

public void function(int n)
   for(int i = n; i > 0; i/=3)
       for(int j = 0; j < i; j++)
           System.out.println("Hello");
       
   

这是算法。 据我所知时间复杂度。它定义了运行时间如何受到输入数量的影响。

所以如果我们举个例子 如果'n'是10。 外循环运行 log n 次,内循环运行 'i' 次。

内部循环相对于 'i' 而不是 'n' 运行。 所以我对如何计算时间复杂度有点困惑。 我认为是 O(log n)。如果我错了,请纠正我。

是 O(log n) 还是 O (n log n) 或 (n^2)。 这个你能帮我吗。 谢谢。

【问题讨论】:

代码中似乎有错误。变量 i 初始化为 0,0 乘以 3 仍为 0。它陷入了无限循环 【参考方案1】:

我会尽量用最简单的术语来解释

外部循环将简单地以 3 次为底运行 log(n)。

因为,i 每次都减少 3 倍。完成的总功等于:

n + n/3 + n/9 + n/27 + .... n/(3^log(n))

因为,n/3 + ... + n/(3^log(n)) 将永远小于 n

例如让 n = 100 那么,100 + 100/3 + 100/9 + 100/27 + ... = 100 + (33.3 + 11.11 + 3.7 + ...)

我们可以清楚地看到括号中的项总是小于100

整个解决方案的总时间复杂度为 O(n)。

【讨论】:

。在你回答的后半部分,我相信你正在描述内部循环所做的工作。我正确吗? 是的,n个工作在内循环的第一次迭代中完成,n/3在内循环的第二次迭代中完成,依此类推... 其实内循环的总迭代次数好像是~n*k/(k-1)(其中k是对数的底),即n*3/2在这种情况下。 一些数学事实:1 + 1/3 + 1/9 + ... = 3/2 是的,我们可以使用 GP sum 公式得到这个结果。【参考方案2】:

实际上它永远不会终止,因为i=0 和更新是i *= 3 所以i 将保持0 所以我们可以说O(+oo)

假设你的意思是for(int i =1...,那么它的O(n)

外循环显然是 O(log_3 n) 因为我们一直乘以 3 内部循环将执行O(log_3 n) 次,迭代计数为(1 + 3 + 9 + 27 + ... + 3^log_3(n)),这显然是一个几何级数,求解得到大约3^log_3(n)),根据日志规则得到n,所以这个循环需要O(n)对于所有迭代,总复杂度为O(n)

【讨论】:

抱歉代码有一点小错误,请查看更新版本@Photon【参考方案3】:

为您的代码:

for(int i = n; i > 0; i/=3)
   for(int j = 0; j < i; j++)
       System.out.println("Hello");
   

内循环变量 j 取决于外循环变量 i,因此您的内循环将决定算法的复杂性。 因为 j 在第一次运行时会运行 'n' 次,在第二次运行时会运行 'n/3' 次等等。因此你的总复杂度可以计算为

n + n/3 + n/9 + n/27 + .......

导致 O(n)

【讨论】:

一些数学事实:1 + 1/3 + 1/9 + ... = 3/2【参考方案4】:

所以这是一个很好的问题!这是一个需要更多思考才能分析的棘手问题。

正如其他一些答案中正确说明的那样,外循环:

for(int i = n; i > 0; i/=3)

将运行 log(n) 次。特别是 log_3(n) 次,但在大 O 表示法中,我们不经常担心基数,所以 log(n) 就可以了。

现在嵌套循环有点棘手:

for(int j = 0; j < i; j++)

乍一看,您可能会认为这是一个简单的 log(n) 循环,但让我们看的更远一些。 所以在第一次迭代中,这将运行 N 次,因为 i 的值为 n。下一次迭代它将运行 n/3 次。然后是 n/9、n/27、n/81 等......

如果我们对这个系列求和,很明显它的总数将小于 2n。 因此我们可以得出结论,该算法的复杂度为 O(n)。

【讨论】:

【参考方案5】:

在你的代码 sn-p:

for (int i=0; i < n; i*=3)  
    for (int j=0; j < i; j++) 
        System.out.println("Hello");
    

i 中的外部循环是O(log_3(n)),因为循环的每个增量都会将i 达到n 所需的接地量减少 3 倍。这是对数行为 (log_3在这种情况下)。 j 中的内部循环简单地迭代了与i 的外部值相同的次数,因此我们可以将外部复杂度平方,得出:

O(log_3(n)^2)

【讨论】:

以上是关于这个算法的时间复杂度是多少的主要内容,如果未能解决你的问题,请参考以下文章

这个5行Java算法的时间复杂度是多少?

这个计算向量中值的最小差的函数的算法复杂度是多少?

算法的时间空间复杂度详解

算法复杂度中的O(logN)底数是多少

以下递归算法的时间复杂度是多少?

三和算法的时间复杂度是多少