sum = 0;
for(int i = 0; i < N; i++)
for(int j = i; j >= 0; j--)
sum++;
据我所知,第一行是1次操作,第2行是(i+1)
次操作,第3行是(i-1)
次操作,第4行是n
次操作。这是否意味着运行时间为1 + (i+1)(i-1) + n
?只是这些让我困惑的最后一步。
答案 0 :(得分:6)
要分析算法,您不想逐行询问“此特定行有多长时间贡献?”原因是每行不执行相同的次数。例如,与仅运行一次的第一行相比,最里面的行执行了很多次。
要分析这样的算法,请尝试识别其值在算法总运行时间的常数因子内的一些数量。在这种情况下,该数量可能是“行sum++
执行多少次?”,因为如果我们知道这个值,我们就知道算法中两个循环花费的总时间。为了解决这个问题,让我们来看看这些循环会发生什么。在外循环的第一次迭代中,i == 0
因此内部循环将只执行一次(从0倒数到0)。在外循环的第二次迭代中,i == 1
与内循环执行恰好两次(先用j == 1
,一旦与j == 0
。更一般地,关于外部环路的第k次迭代,内循环执行k + 1
次。这意味着最内层循环的迭代总数由
1 + 2 + 3 + ... + N
此数量可以显示为等于
N (N + 1) N^2 + N N^2 N
--------- = ------- = --- + ---
2 2 2 2
这两个术语,在N^2 / 2
术语是主导生长的术语,并且因此,如果我们忽略它的常数因子,我们得到的O的运行时(N 2 )。
不要把这个答案视为你应该记住的东西 - 想一想得到答案所需的所有步骤。我们首先找到一些要计算的数量,然后看看这个数量是如何受到循环执行的影响。由此,我们能够得到该数量的数学表达式,然后我们将其简化。最后,我们得到了结果表达式并确定了主导项,它作为整体函数的大O.
答案 1 :(得分:2)
从里到外工作。
sum++
这是一个单独的操作,因为它不重复。
for(int j = i; j >= 0; j--)
这循环i + 1次。那里有几个操作,但您可能并不是要计算asm指令的数量。所以我假设这个问题是i + 1的乘数。由于循环内容是单个操作,因此循环及其块执行i + 1操作。
for(int i = 0; i < N; i++)
这循环N次。和之前一样,这是N的乘数。由于块执行i + 1运算,因此该循环总共执行N(N + 1)/ 2次运算。这就是你的答案!如果你想考虑大O复杂性,那么这简化为O(N 2 )。
答案 2 :(得分:1)
它不是附加的:内部循环在外循环的每次迭代中发生一次。所以它是O(n 2 )。
顺便说一句,这是为什么我们为这种事情使用渐近符号的一个很好的例子 - 取决于“操作”的定义,计数的确切细节可能变化很大。 (比如,sum++
是单个操作,还是add sum to 1 giving temp; load temp to sum
?)但是因为我们知道所有这些都可以隐藏在一个常数因子中,所以它仍然是O(n 2功能)。
答案 3 :(得分:0)
没有;您不计算每行的特定操作数,然后将其添加。像'for'这样的结构的整个要点是使给定的代码行可以运行多次。您应该使用思维和逻辑技能来计算“sum ++”行将运行的次数,作为N的函数。提示:每次遇到第三行时它都会运行一次。
遇到第二行的次数是多少次?
每次遇到第二行时,都会设置“i”的值。第三行使用的值运行多少次?因此,整体运行多少次? (提示:如果我在几个不同的场合给你不同的金额,你怎么知道我给你的总金额?)
每次遇到第三行时,第四行都会发生一次。
哪条线最常出现?根据N?
,它经常发生的次数答案 4 :(得分:0)
因此,猜测你感兴趣的是总和++以及执行它的时间。
总和的最终统计数据会给你答案。
实际上你的循环只是:
Sigma(n)n从1变为N.
等于:N*(N+1) / 2
这会给你一个大概念O(N^2)
除了问题名称旁边,算法中没有最坏的情况。 或者你可以说最坏的情况是当N变为无穷大时。
答案 5 :(得分:0)
使用Sigma表示法表示您的循环: