程序的时间复杂性

时间:2016-11-23 13:33:11

标签: algorithm time-complexity big-o

我只是在学习时间复杂性,这是我编写的一段代码

for (int i = 1; i <= N; i++)
  for (int j = 1; j <= N; j++)
  {
    // Spread Peace
  }

显然,上面的一个是 O(N ^ 2)的复杂性,它似乎(N == 1e6)可以永远运行。

这是第二段代码

for (int i = 1; i <= N; i++)
  for (int j = i; j <= N; j++)
  {
    // Money is Everything
  }

以上一个也 O(N ^ 2) - N *(N + 1)/ 2 复杂性也在永远运行,但是这段代码:

for (int i = 1; i <= N; i++)
  for (int j = i; j <= N; j += i)
  {
    // Be my GirlFriend
  }

只是在一秒钟内执行,我无法得出它的时间复杂度为什么这么快?什么是N == 1e6估算

2 个答案:

答案 0 :(得分:4)

让我们首先执行实验,让我们尝试展开循环( C#implementation ),看看发生了什么:

 private static IEnumerable<String> Unroll(int N) {
  for (int i = 1; i <= N; i++) {
    StringBuilder sb = new StringBuilder();

    for (int j = i; j <= N; j += i) {
      if (sb.Length > 0)
        sb.Append(", ");

      sb.Append(j);
    }

    yield return sb.ToString();
  }

使用较小数字(例如16)的测试运行会显示图片

  Console.Write(string.Join(Environment.NewLine, Unroll(16)));

你能看到模式,指数下降吗?它看起来像N * log(N),对吧?

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
2, 4, 6, 8, 10, 12, 14, 16
3, 6, 9, 12, 15
4, 8, 12, 16
5, 10, 15
6, 12
7, 14
8, 16
9
10
11
12
13
14
15
16

现在是纸和笔的时候了:我们有(对于大N

   N / 1 items (step == 1) +
   N / 2 items (step == 2) +
   N / 3 items (step == 3) +
   ...
   N / N items (step == N)
------------------------------
   N * (1 + 1/2 + ... + 1/N) = 
   N * H(N) = 
   O(N * log(N)) // Harmonic sum H(N) gives log(N)  

更准确的估算

   H(N) = ln(N) + gamma + 1/(2*N) + ...

,其中

   ln()  - natural logarithm
   gamma - Euler–Mascheroni constant (0.5772156649...)

为您提供N == 1e6关于14.4e6循环的信息,实际上有点高估了;实际计数为1397003414.0e6),因为当使用Harmonic系列进行近似时,我们没有采用整数除法(每个k/N应该整数< / em>,即不考虑k/N,但floor(k/N))。

答案 1 :(得分:0)

您可以继续使用Sigma表示法:

enter image description here

有关谐波函数的更多信息,请访问:Asymptotic analysis