Time complexity for循环的时间复杂性,我无法真正理解一件事

Time complexity for循环的时间复杂性,我无法真正理解一件事,time-complexity,Time Complexity,所以这些是for循环,我必须找到时间复杂度,但我并不清楚如何计算 for (int i = n; i > 1; i /= 3) { for (int j = 0; j < n; j += 2) { ... ... } for (int k = 2; k < n; k = (k * k) { ... } for(int i=n;i>1;i/=3){ 对于(int j=0;j

所以这些是for循环,我必须找到时间复杂度,但我并不清楚如何计算

for (int i = n; i > 1; i /= 3) {
    for (int j = 0; j < n; j += 2) {
        ... ...
    }
    for (int k = 2; k < n; k = (k * k) {
        ...
    }
for(int i=n;i>1;i/=3){
对于(int j=0;j
对于第一行,(inti=n;i>1;i/=3),保持i除以3,如果i小于1,则循环停止在那里,对吗

但它的时间复杂度是多少?我想是n,但我不是很确定。 我认为它是n的原因是,如果我假设n是30,那么我会像30,10,3,1,然后循环停止。它运行n次,不是吗

对于最后一个for循环,我认为它的时间复杂度也是n,因为它所做的是

k以2开始,并不断地自身相乘,直到k大于n

所以如果n是20,k将是2,4,16,然后停止,它也运行n次

我真的不认为我理解这类问题,因为时间复杂度可以是log(n)或n^2等,但我看到的只是n

我真的不知道什么时候是圆木或正方形,或者其他什么

我想,每个for循环运行n次,如何参与日志或平方


有人能帮我理解吗?请。

tl;dr;我先介绍几个例子,我在这篇文章的底部分析了OP问题的复杂性

简而言之,大O表示法告诉您,如果您缩放输入,程序将如何执行

想象一个计数为100的程序(P0)。无论你多久运行一次程序,它都会以同样快的速度计数到100(给予或接受)。显然是这样吗

现在想象一个程序(P1)它计数到一个可变的数字,也就是说,它将一个数字作为它计数的输入。我们称这个变量为
n
。现在每次P1运行时,P1的性能都取决于
n
的大小。如果我们将
n
设为100,P1将运行得非常快。如果我们将
n
设为等于googleplex,它将运行得非常快再等一会儿

基本上,P1的性能取决于
n
的大小,这就是我们说P1具有时间复杂性
O(n)
的意思

现在想象一个程序(P2),我们计算的是
n
的平方根,而不是它本身。显然P2的性能会比P1差,因为它们计算的数字相差很大(特别是对于较大的
n
(=缩放))。凭直觉你会知道P2的时间复杂度等于
O(n^2)
如果P1的复杂性等于
O(n)

现在考虑一个看起来像这样的程序(P3):

var length= input.length;
for(var i = 0; i < length; i++) {
    for (var j = 0; j < length; j++) {
        Console.WriteLine($"Product is {input[i] * input[j]}");
    }
}
如果我们进行分析,我们可以这样说:

  • 第一行代码被执行
    O(cbrt(3))
    次,其中
    cbrt
    是其输入的立方根。由于
    i
    被每个循环除以3,因此
    n
    的立方根是
    i
    小于或等于1之前需要执行循环的次数
  • 的第二个
    循环在时间上是线性的,因为执行了
    j
    O(n/2)
    倍,因为它增加了2而不是1 因为我们知道,
    O(n/2)=O(n)
    ,我们可以说 这个for循环被执行
    O(cbrt(3))*O(n)=O(n*cbrt(n))
    次(第一次
    for
    *嵌套的
    for
  • 对于,第三个
    也嵌套在第一个
    中,但是由于它没有嵌套在第二个
    中,所以我们不打算将其乘以第二个(显然,因为每次执行第一个
    for
    ,它都会被执行)这里,
    k
    n
    的约束,但是由于它每次都是由自身的一个因子增加的,我们不能说它是线性的,也就是说,它的增加是由一个变量定义的,而不是由一个常数定义的。由于我们将
    k
    增加自身的一个因子(我们将其平方),它将在
    2
    log(n)中达到
    n
    步骤。如果您了解
    日志的工作原理,那么推断这一点很容易,如果您不了解这一点,那么您需要首先了解它。在任何情况下,由于我们分析该for循环将运行
    O(
    2
    log(n))
    时间,第三个
    for
    的总复杂度为
    O(cbrt(3))*O(
    2
    log(n))
    =
    O(cbrt(n)*
    2
    log(n))
  • 程序的总时间复杂度现在由不同的子时间复杂度之和计算:
    O(n*cbrt(n))+O(cbrt(n)*
    2
    log(n))

正如我们之前看到的,如果我们谈论大O表示法,我们只关心增长最快的术语,所以我们说您的程序的时间复杂性等于
O(n*cbrt(n))
tl;dr;首先,我描述了几个例子,我在本文底部分析了OP问题的复杂性

简而言之,大O表示法告诉您,如果您缩放输入,程序将如何执行

想象一个计数为100的程序(P0)。无论你多久运行一次程序,它都会以同样快的速度计数到100(给予或接受)。显然是这样吗

现在想象一个程序(P1)它计数到一个可变的数字,也就是说,它将一个数字作为它计数的输入。我们称这个变量为
n
。现在每次P1运行时,P1的性能都取决于
n
的大小。如果我们将
n
设为100,P1将运行得非常快。如果我们将
n
设为等于googleplex,它将运行得非常快再等一会儿

基本上,P1的性能取决于
n
有多大,这就是我们说P1有多大的意思
for (int i = n; i > 1; i /= 3) {
    for (int j = 0; j < n; j += 2) {
        ... ...
    }
    for (int k = 2; k < n; k = (k * k) {
        ...
    }
}
T = function(n) {
  var m = 0;
  for (var i = n; i > 1; i /= 3) {
    for (var j = 0; j < n; j += 2)
      m++;
    for (var k = 2; k < n; k = k * k)
      m++;
  }
  return m;
}

M = function(n) {
  return ceil(log(n)/log(3)) * (floor(n/2) + ceil(log2(log2(n))));
}
n       T(n)    M(n)
-----------------------
100000  550055  550055
105000  577555  577555
110000  605055  605055
115000  632555  632555
120000  660055  660055
125000  687555  687555
130000  715055  715055
135000  742555  742555
140000  770055  770055
145000  797555  797555
150000  825055  825055