我有以下内容:
public static int[] MyAlgorithm(int[] A, int n) {
boolean done = true;
int j = 0;
while(j <= n - 2) {
if(A[j] > A[j+1]) {
int temp = A[j + 1];
A[j + 1] = A[j];
A[j] = temp;
done = false;
}
j++;
}
j = n - 1;
while(j >= 1) {
if(A[j] < A[j-1]) {
int temp = A[j - 1];
A[j - 1] = A[j];
A[j] = temp;
done = false;
}
j--;
}
if(!done)
return MyAlgorithm(A, n);
else
return A;
}
这基本上对长度为'n'的数组'A'进行排序。但是,在试图弄清楚这个算法的时间复杂度之后,我不断碰到圈子。如果我看一下第一个while循环,循环中的内容将执行'n-2'次,从而使其成为O(n)。第二个while循环在'n-1'次执行,因此只要我们删除了两个函数的常量就使它成为O(n)。现在,这个算法的递归部分再次引发了我的兴趣。
递归看起来是尾递归的,因为它之后不会调用任何其他东西。此时,我不确定尾递归的递归是否与这个时间复杂度有关...如果这真的是O(n)这是否也意味着它也是Omega(n)?
如果有的话,请更正我所做的任何假设。任何提示都会很棒!
答案 0 :(得分:4)
这是O(n 2 )。
这是因为每次递归都会迭代整个数组两次。一旦上升(将最高的答案冒泡到顶部)并一次向下(将最低的答案冒泡到底部)。
在下一次迭代中,你还有另一个2n。但是,我们知道最顶层和最底层的元素是正确的。因此我们知道我们有n-2个未排序的元素。重复时,您将再排序2个元素,依此类推。如果我们想要找到迭代次数,那么我们求解n - 2i = 0. i = n / 2次迭代。
n / 2次迭代*每次迭代2n次操作= n 2 操作。
编辑:尾递归对时间顺序没有帮助,但是它可以帮助一些语言进行内存处理。我不能确切地说它是如何工作的,但是它以某种方式显着减少了所需的堆栈空间。另外,我对此有点生疏,但O表示法表示最坏情况,而欧米茄表示法表示最佳情况。这是Omega(n),因为最好的情况是它迭代数组两次,发现所有内容都已排序,并且没有递归。
答案 1 :(得分:1)
在您的情况下,递归关系类似于:
T(n)= T(n)+ n。
但如果我们假设最大的没有。 在每种情况下都会最终结束。我们可以近似:
T(n)= T(n-1)+ n
T(n-1)= T(n-2)+ n-1
t(n-2)= T(n-3)+ n-2
T(n)= T(n-2)+ n-1 + n
T(n)= T(n-3)+ n-2 + n-1 + n
T(n)= T(n-k)+ kn -k(k-1)/ 2
如果n-k = 1
然后k = n + 1 替代
T(n)= T(1)+ n(n + 1) - (n + 1)(n)/ 2
订单O(n ^ 2)
也是最小的没有。将在开始时结束,所以我们也可以近似。
T(n)= T(n-2)+ n
仍然是O(n ^ 2)
如果删除了该近似值,我们无法准确估计何时 完成将是真的。但在这种情况下,我们可以肯定最大的没有 在每次迭代后总是会在最后结束,而在开始时最小,所以不会为0和n-1做任何事情。
我希望这可以帮助你理解为什么n ^ 2。