如何计算时间复杂度?

时间复杂度说白了就是运行一个算法需要消耗多少CPU指令周期,但是这个计算非常受到软硬件环境的影响,比如
A=A+B;
如果A是32位数,B也是32位数,所在的环境是32位机,这句话只需要1个指令周期即可完成。
但是如果A是64位数,B也是64位数,环境是32位机,这句话需要6个指令周期才能完成。
另一方面,对于稍微复杂一点的程序,精确计算CPU指令周期几乎是个不可能的,所以我们需要简化它。
因此,为了屏蔽环境影响,并且为了简化,我们只用渐进趋势来估计时间复杂度。所谓渐进趋势,就是n趋于无穷大的时候,算法复杂度趋于n的哪个函数。

下面是引入一些数学上的定义:
1. 如果存在正常数c和n,使得当N>n时,T(N)<=cf(N),则记为T(N)=O(f(N))
2. 如果存在正常数c和n,使得当N>n时,T(N)>=cg(N),则记为T(N)=Ω(g(N))
3. T(N)=θ(h(N)),当且仅当T(N)=O(h(N))且T(N)=Ω(h(N))
4. 如果T(N)=O(p(N))且T(N)!=θ(p(N)),则T(N)=o(P(N))

实际应用当中,在使用θ时,许多人更愿意用O;另外,当需要用到Ω时,还是使用O。。。所以我们平时经常见到O,而几乎没有见到别的符号。

有一个可用的方法来确定f(N)和g(N)的关系,即洛必塔法则:
若lim f(N)=无穷且 lim g(N)=无穷,则lim f(N)/g(N)=lim f(N)的导数/g(N)的导数
若结果0,f(N)=o(g(N));
若极限是c!=0,f(N)=θ(g(N))
极限是∞,g(N)=o(f(N))
极限摆动,二者无关

递归的算法如何计算算法复杂度?

比如Fibonacci数列,它的递归算法如下:
long int Fib(int N){
     if(N<=1)
          return 1;
     else
          return Fib(N-1)+Fib(N-2);
}
计算输入为N的运行时间值是T(N)=T(N-1)+T(N-2)+2; 后面的那个2是Fib(0)和Fib(1)的时间。

那么怎么求Fib(N)的时间复杂度呢?我们可以用数学归纳法证明Fib(N)<(5/3)的N次方,同样我们也可以用同样的方法证明Fib(N)>=(3/2)的N次方。因此递归的函数很难直观的计算复杂度。


下面有几个例子:

Example 1:
int a=0;
for(int i=0;i<N;i++){
for(int j=0;j<i;j++) {
     a++;
}
这个例子里面,算法复杂度是O(1+2+3...N-2), 按照等差数列求和公式,应该是 O((N-1)*(N-2)),所以算法复杂度是O(N的平方)

Example 2:

对于一个字节(8bit)的无符号整形变量,求其二进制表示中 “1” 的个数,要求算法的执行效率尽可能高。

解法1:
int Count(BYTE v){
     int num=0;
     while(v){
          num+=v&0x01;
          v>>=1;
     }
     return num;
}
这种算法的复杂度是多少呢?
它计算了log(v)次,也就是v的二进制位数。

解法2:
int Count(BYTE v){
     int num=0;
     while(v){
          v&=(v-1);
          num++;
     }
     return num;
}
算法复杂度为v中1的个数

解法3:

写一个Hash表,用空间换时间,这样算法复杂度为O(1)


一些常见的算法复杂度:

O(1)
基本运算, +,-,*,/,%,寻址
Hash的期望复杂度(不碰撞的情况下)
O(logn)
二分查找
O(n1/2)
枚举约数
O(n)
线性查找
建立堆
O(nlogn)
归并排序
快速排序的期望复杂度
基于比较排序的算法下界

O(n2)

集合里枚举所有二元组,朴素最近点对
O(n3) 
集合里枚举三元组
Floyd最短路
普通矩阵乘法
O(2的n次方) 
枚举全部的子集
O(2的n次方*n)
TSP的动态规划算法
O(n!)
枚举全排列
O(n的n次方)
枚举[1..n]的n维数组的全部元素……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值