三重嵌套for循环的运行时

时间:2017-07-05 04:56:12

标签: performance for-loop time-complexity big-o

我目前正在阅读“破解编码面试”教科书,我正在审查Big-O和运行时。其中一个例子就是这样:

  

将所有正整数解打印到等式a ^ 3 + b ^ 3 = c ^ 3 + d ^ 3其中a,b,c,d是1到1000之间的整数。

提供的伪代码解决方案是:

n = 1000;
for c from 1 to n
  for d from 1 to n
    result = c^3 + d^3
    append (c,d) to list at value map[result]

for each result, list in map
  for each pair1 in list
    for each pair2 in list
      print pair1, pair2

The runtime is O(N^2)

我不确定如何获得O(N ^ 2),经过广泛的谷歌搜索并试图找出原因后,我仍然不知道。我的理性如下:

  1. 上半部分是O(N ^ 2),因为外部循环到n,内部循环每次执行n次。
  2. 下半部分我不知道如何计算,但是我得到O(地图的大小)* O(列表的大小)* O(列表的大小)= O(地图的大小)* O(大小的列表^ 2)。
  3. O(N ^ 2)+ O(地图的大小)* O(列表的大小^ 2)
  4.   

    2个for循环将对添加到map列表中= O(N)* O(N)b / c它是2个循环运行N次。

         

    迭代地图的外部for循环= O(2N-1)= O(N)b / c地图的大小是2N - 1,基本上是N.

         

    用于迭代每个列表对的2个for循环= O(N)* O(N)b / c每个列表是< = N

         

    总运行时间:O(N ^ 2)+ O(N)* O(N ^ 2)= O(N ^ 3)

         

    不确定我在这里缺少什么

    有人可以帮我弄清楚O(N ^ 2)是如何获得的,或者为什么我的解决方案不正确。对不起,如果我的解释有点令人困惑。感谢

3 个答案:

答案 0 :(得分:0)

基于解的第一部分,sum(列表的大小)== N.这意味着第二部分(嵌套循环)不能比O(N ^ 2)更复杂。正如你所说,复杂性是O(size of map)*O(size of list^2),但它应该是:

O(size of map)*(O(size of list1^2) + O(size of list2^2) + ... )

这意味着,在最坏的情况下,我们将得到一张大小为1的地图,一张大小为N的列表,以及由此产生的O(1)*O((N-1)^2) <==> O(N^2)

的复杂性

在其他情况下,复杂性会降低。例如,如果我们有2个元素的映射,那么我们将得到2个总大小为N的列表。那么结果就是:

O(2)*( O(size of list1^2) + O(size of list2^2)), where (size of list1)+(size of list2) == N

我们从基本数学知道X ^ 2 + Y ^ 2&lt; =(X + Y)^ 2为正数。

答案 1 :(得分:0)

第二部分的复杂性是O(sum of (length of lists)^2 in map),因为列表的长度取决于我们知道sum of length of lists in map是n ^ 2,因为我们肯定在第一位添加了n ^ 2对的代码。从T(program) = O(n^2) + O(sum of length of lists in map) * O(sum of length of lists in map / size of map) = O(n^2) * O(sum of length of lists in map / size of map)开始,仍然显示sum of length of lists in map / size of map是O(1)。这样做需要相当多的数论,不幸的是我无法帮助你。但请查看这些链接,了解有关如何处理的更多信息:https://en.wikipedia.org/wiki/Taxicab_number
https://math.stackexchange.com/questions/1274816/numbers-that-can-be-expressed-as-the-sum-of-two-cubes-in-exactly-two-different-w
http://oeis.org/A001235

答案 2 :(得分:0)

这是一个非常有趣的问题! cdo256提出了一些好处,我将尝试解释一下并完成图片。

关键问题或多或少是显而易见的 - 存在多少个整数,可以用k个不同的方式(k >= 2)表示为两个正立方的总和,什么是k的可能大小?此数字确定列表的大小,这些列表的值为map,这决定了程序的总复杂程度。我们的搜索空间&#34;从2到2 * 10 ^ 9,因为cd都从1到1000迭代,所以它们的多维数据集的总和最多为2 * 10 ^ 9。如果[2,2 * 10 ^ 9]范围内的数字都不能以多种方式表示为两个立方体的总和,那么我们程序的复杂度将为O(n^2)。为什么?好吧,第一部分显然是O(n^2),第二部分取决于map值的列表大小。但在这种情况下,所有列表的大小均为1,并且地图中有n^2个键,其中包含O(n^2)

但事实并非如此,有一个着名的例子是&#34;出租车号码&#34; 1729,让我们回到我们的主要问题 - 将整数表示为两个正整数立方体之和的不同方法的数量。这是一个活跃的数论研究领域,并在Joseph H. Silverman的文章Taxicabs and Sums of Two Cubes中给出了很好的总结。我建议仔细阅读。目前的记录是here。一些有趣的事实:

  • 最小整数,可以用三种不同的方式表示为两个正整数立方体的总和是87,539,319
  • 可以用四种不同方式表示为两个正整数立方体之和的最小整数是6,963,472,309,248(> 2 * 10 ^ 9)
  • 可以用六种不同方式表示为两个正整数立方体之和的最小整数是24,153,319,581,254,312,065,344(> 2 * 10 ^ 9)

正如您可以轻易看到的那样here,范围[2,2 * 10 ^ 9]中只有2184个整数,可以用两种或三种不同的方式表示为两个正立方的总和,对于k = 4,5,..,这些数字都是我们的范围。因此,map中的键数非常接近n^2,值列表的大小最多为3,这意味着代码的复杂性

  for each pair1 in list
    for each pair2 in list
      print pair1, pair2

是常数,因此总复杂度再次为O(n^2)