根据语句执行的次数确定以下代码示例的精确Big-Oh值。
请牢记以下注意事项:
代码示例:
for (int i = 0; i < n; i++){
for (int j = i; j < n; j++){
sum += i;
}
}
上面的答案是O(4N ^ 2 + 5N + 2),但我不确定如何计算答案。我试图更好地了解如何计算死刑。
答案 0 :(得分:1)
该代码的复杂性的大O是O(N^2)
。其他任何答案都基于对Big O记号的数学定义和/或编写它的惯例的误解 1 。
您说“上面的答案是O(4N^2 + 5N + 2)
”。不对指令计数(根据有关指令和编译器的某些假设)可能是4N^2 + 5N + 2
。但是,这不是为函数编写Big O复杂度类的常规方法。
复杂度类不是函数。它是满足特定数学属性的无穷函数集。约定是使用集合中所有功能中最简单的一个来描述复杂性类。
1-有人认为使用非标准/非常规的Big O表示法是不正确的。然而,这违背了使用数学符号的目的……这是数学思想从一个人到另一个人的清晰交流。打个比方:如果我写了1 + 1 is 11
,从技术上讲我可能是对的(使用一元符号表示),但这是史诗般的失败,作为传达想法1 + 1 = 2
的一种方式。
我的老师要求执行的“精确”数量。
嗯:
那不是什么大事。
这不是一个特别有用的措施,因为在使用 real 编译后, real 指令会在 real 硬件上进行计数> real 编译会有所不同。
您说:
我相信每一行代码都有一定数量的执行
问题在于,“执行”的数量取决于您定义原始操作的方式以及将Java代码编译为原始操作的方式。
例如,有多种方法可以将示例中的嵌套循环编译为指令,这些指令将给出要执行的不同数量的原始跳转。 (请考虑循环展开和/或大量的switch语句。)
Nikos的回答说明了这一点。他对指令进行了仔细的核算(根据他对原始操作的解释),并为您的老师提出了一个不同公式。谁是正确的?可能都是...根据假设。
答案 1 :(得分:1)
您说答案是 O(4N ^ 2 + 5N + 2),但实际上,如果简化为BIG O,答案将是O(N ^ 2)。
O(4N ^ 2 + 5N + 2 + 不超过 N ^ 2 )还原为O(N ^ 2)。
如果将来您发现在循环中发现复杂性而感到震惊,我会尝试给您提示。
1。。如果函数的时间复杂度不包含循环,递归和对任何其他非恒定时间函数的调用,则将其视为 O(1) ,以您的情况sum += i;
2。。如果循环变量递增/递减恒定量,则循环的时间复杂度被视为 O(n),在您的情况下,内部循环将如果单独考虑,则复杂度为O(N)。
3。。嵌套循环的时间复杂度等于执行最里面的语句的次数。在您的情况下O(N ^ k)-> O(N ^ 2)
将1 + 2 + 3组合起来可以得到O(N ^ 2)
答案 2 :(得分:1)
正如史蒂芬(Stephen)所述,实际的算法复杂度简化为O(N^2)
,但是由于您的问题是要测量执行量,因此我将尽力为您计数。
for (int i = 0; i < n; i++){
for (int j = i; j < n; j++){
sum += i;
}
}
首先是外循环
int i=0
将只执行一次。
i < n
将执行n+1
次
i++
将执行n
次
因此,我们有2n+2
个执行用于外部循环。
让我们先清除一些东西。外循环将运行n
次,内循环将运行n/2
次(平均)。因此,内部循环中的每条指令将执行n * n/2 = (n^2)/2
次。
内循环
int j = i
将执行n
次(请记住它处于循环状态)
j< n
将执行n+1 * n/2 = (n^2)/2 + n/2
次
j++
将执行n*(n/2) = n^2/2
次
现在,请记住内部循环中的每条指令将运行(n^2)/2
次。
sum += i
基本上是2次执行,每次将执行n^2/2
次。因此,这又添加了n^2
个处决
总共添加:(2n + 2) + n + (n^2)/2 + n/2 + (n^2)/2 + n^2 = 2n^2 + (7/2)n + 2
添加跳转指令,即外循环为n
,内循环为n^2/2
,则总数为(5/2)n^2 + (9/2)n + 2
。
无论我还是您的教授都错过了一些东西,希望对您有所帮助,因为它可能使您对如何计算死刑数量有所了解。我不知道为什么这很有用