递归算法的时间复杂度
Time complexity of algorithm with recursion
我有以下内容:
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)?
如果有任何假设,请更正我所做的任何假设。任何提示都会很棒!
这是O(n2)。
这是因为每次递归时,您都会将整个数组迭代两次。向上一次(将最高答案冒泡到顶部)和一次向下(将最低答案冒泡到底部)。
在下一次迭代中,您还有另一个 2n。但是,我们知道最顶层和最底层的元素是正确的。因此我们知道我们有 n-2 个未排序的元素。当它重复时,您将再对 2 个元素进行排序,依此类推。如果我们想找到迭代次数 "i",那么我们求解 n - 2i = 0. i = n/2 次迭代。
n/2 次迭代 * 每次迭代 2n 次操作 = n2 次操作。
编辑:尾递归并不能真正帮助时间顺序,但它确实有助于某些语言的内存处理。我不能确切地说出它是如何工作的,但它以某种方式显着减少了所需的堆栈 space。
此外,我对此有点生疏,但 O 表示法表示最差情况,而 Omega 表示法表示最佳情况。这是 Omega(n),因为最好的情况是它迭代数组两次,发现所有内容都已排序,并且不递归。
在你的例子中,递归关系是这样的:
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。
我有以下内容:
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)?
如果有任何假设,请更正我所做的任何假设。任何提示都会很棒!
这是O(n2)。
这是因为每次递归时,您都会将整个数组迭代两次。向上一次(将最高答案冒泡到顶部)和一次向下(将最低答案冒泡到底部)。
在下一次迭代中,您还有另一个 2n。但是,我们知道最顶层和最底层的元素是正确的。因此我们知道我们有 n-2 个未排序的元素。当它重复时,您将再对 2 个元素进行排序,依此类推。如果我们想找到迭代次数 "i",那么我们求解 n - 2i = 0. i = n/2 次迭代。
n/2 次迭代 * 每次迭代 2n 次操作 = n2 次操作。
编辑:尾递归并不能真正帮助时间顺序,但它确实有助于某些语言的内存处理。我不能确切地说出它是如何工作的,但它以某种方式显着减少了所需的堆栈 space。
此外,我对此有点生疏,但 O 表示法表示最差情况,而 Omega 表示法表示最佳情况。这是 Omega(n),因为最好的情况是它迭代数组两次,发现所有内容都已排序,并且不递归。
在你的例子中,递归关系是这样的:
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。