MDGSF Software Engineer

时间复杂度分析

2016-05-14
Art

例1

下面算法的时间复杂度是____
int foo(int n) {
    if (n <= 1) {
        return 1;
    }
    return n * foo(n - 1);
}

我们要做的第一步便是确定关键操作,这里的关键操作显然是if语句,那么我们只需要判断if语句执行的次数即可。首先我们看到这是一个递归过程:foo会不断的调用自身,直到foo的实参小于等于1,foo就会返回1,之后便不会再执行if语句了。由此我们可以知道,if语句调用的次数为n次,所以时间复杂度为O(n)。

例2

以下函数的时间复杂度为____
void recursive(int n, int m, int o) {
    if (n <= 0) {
        printf("%d, %d\n", m, o);
    } else {
        recursive(n - 1, m + 1, o);
        recursive(n - 1, m, o + 1);
    }
}

首先,它的关键操作时if语句,因此我们只需判断出if语句的执行次数即可。以上函数会在n > 0的时候不断递归调用自身,我们要做的是判断在到达递归的base case(即n <= 0)前,共执行了多少次if语句。我们假设if语句的执行次数为T(n, m, o),那么我们可以进一步得到:T(n, m, o) = T(n-1, m+1, o) + T(n-1, m, o+1) (当n > 0时)。我们可以看到base case与参数m, o无关,因此我们可以把以上表达式进一步简化为T(n) = 2T(n-1)。

由此我们可得:

T(n) = 2T(n-1)
     = (2^2) * T(n-2)
     = (2^3) * T(n-3)
     = ...
而很明显T(1) = 2
所以:
T(1) = 2
T(2) = 2T(n-1) = 2 * T(1) = 2 * 2 = 2^2
T(3) = (2^2) * T(n-2) = (2^2) * T(1) = 2^3
T(4) = (2^3) * T(n-3) = (2^3) * T(1) = 2^4
...
T(n) = 2^n

所以我们可以得到以上算法的时间复杂度为O(2^n)。

例3

如下程序的时间复杂度为____(其中m > 1,e > 0)
x = m;
y = 1;
while (x - y > e) {
    x = (x + y) / 2;
    y = m / x;
}
print(x);

以上算法的关键操作即while语句中的两条赋值语句,我们只需要计算这两条语句的执行次数即可。我们可以看到,当x - y > e时,while语句体内的语句就会执行,x = (x + y) / 2使得x不断变小(当y«x时,执行一次这个语句会使x变为约原来的一半),假定y的值固定在1,那么循环体的执行次数即为~logm,而实际情况是y在每次循环体最后都会被赋值为m / x,这个值总是比y在上一轮循环中的值大,这样一来x-y的值就会更小,所以以上算法的时间复杂度为O(logm)。

假设y一直为1,那么:

执行的次数 x的大小
0 m
1 m/2
2 m/(2^2)
3 m/(2^3)
n m/(2^n)
m/(2^n) > 1
令 m/(2^n) = 1
则 n = log(m) 以2为基

例4

假设某算法的计算时间可用递推关系式T(n) = 2T(n/2) + n,T(1) = 1表示,则该算法的时间复杂度为____
T(1) = 1
T(n) = 2T(n/2) + n
T(n/2) = 2T(n/4) + n/2
T(n/4) = 2T(n/8) + n/4
...

所以:
T(n) = 2T(n/2) + n
     = (2^2) * T(n/(2^2)) + 2*n
     = (2^3) * T(n/(2^3)) + 3*n
     = ...

T(1) = 1
T(2) = 2T(n/2) + n = 2T(1) + 2 = 4
T(4) = (2^2) * T(n/(2^2)) + 2*n = (2^2) * T(1) + 2*4 = 12
T(8) = (2^3) * T(n/(2^3)) + 3*n = (2^3) * T(1) + 3*8 = 32
...
T(n) = (2^k) + k*n  (k = logn)
     = n + nlogn

所以时间复杂度为 O(nlogn)

总结

T(1) = 1
T(n) = T(n-1)
时间复杂度: O(1)

T(1) = 1
T(n) = T(n-1) + 1
时间复杂度: O(n)

T(1) = 1
T(n) = 2T(n-1)
时间复杂度: O(2^n)

T(1) = m
T(n) = T(n-1) / 2
时间复杂度: O(logm)

T(1) = 1
T(n) = 2*T(n/2) + n
时间复杂度: O(n + nlogn) = O(nlogn)

weixingongzhonghao

Similar Posts

上一篇 [C/C++] 虚函数

Comments