我首先要求开发一个简单的排序算法,按递增顺序对整数数组进行排序并将其放入代码中:
int i, j;
for ( i = 0; i < n - 1; i++)
{
if(A[i] > A[i+1])
swap(A, i+1, i);
for (j = n - 2; j >0 ; j--)
if(A[j] < A[j-1])
swap(A, j-1, j);
}
现在我有了排序功能,我要求对算法的运行时间进行理论分析。它说答案是O(n ^ 2),但我不太确定如何证明这种复杂性。
到目前为止我所知道的是第一个循环从0到n-1,(所以n-1次),第二个循环从n-2到0,(所以n-2次)。
执行递归关系:
let C(n) = the number of comparisons
for C(2) = C(n-1) + C(n-2)
= C(1) + C(0)
C(2) = 0 comparisons?
C(n) in general would then be: C(n-1) + C(n-2) comparisons?
如果有人可以一步一步指导我,那将非常感激。
答案 0 :(得分:1)
在进行“真正的”大O时间复杂度分析时,选择您计算的一个操作,显然是主导运行时间的操作。在你的情况下你可以选择比较或交换,因为最坏的情况会有很多交换吗?
然后计算这将被引发的次数,缩放到输入。因此,在您的情况下,您的分析非常正确,您只需这样做:
C = O((n - 1)(n - 2)) = O(n^2 -3n + 2) = O(n^2)
我通过推理代码中的数据流来得出这些数字。你有一个外部for循环迭代对吗?在for循环中,你有另一个for循环迭代。第一个for循环迭代n - 1次,第二个for循环n - 2次。由于它们是嵌套的,实际的迭代次数实际上是这两个的乘法,因为对于外部循环中的每次迭代,整个内部循环都会运行,进行n - 2次迭代。
正如您可能知道的那样,在进行时间复杂性分析时,您总是会删除除主导词之外的所有术语。
关于最坏情况的复杂性和平均情况,下限,还有很多要补充的内容,但这有望让您掌握如何推理大O时间复杂度分析。
我已经看到了许多用于实际分析表达式的不同技术,例如你的递归关系。但是我个人更喜欢只是推理代码。很少有算法具有硬上限来计算,另一方面下界通常很难计算。
答案 1 :(得分:0)
您的分析是正确的:外部循环进行n-1
次迭代。内循环使n-2
。
因此,对于外部循环的每次迭代,您在内部循环上进行n-2
次迭代。因此,步骤总数为(n-1)(n-2) = n^2-3n+2
。
主导术语(在大O分析中最重要的)是n^2
,因此你得到O(n^2)
运行时。
在这种情况下,我个人不会使用递归方法。编写递推方程通常对递归函数很有帮助,但是在这样的简单算法中,有时它更容易查看代码并做一些简单的数学运算。