复杂性分析初步

复杂性概念

  空间复杂度:指令空间、数据空间和环境栈空间(递归)
  时间复杂度:由关键操作计数决定,一般将加减乘除和比较操作看作是基本操作(约定每个基本操作所用时间都是一个单位),然后确定程序总的执行步数不能用机器的真正运行时间作衡量标准,因为影响运行时间的因素太多,甚至还有很多未知因素)。

复杂性举例

//寻找a[0:n-1]中的最大元素

template<class T>                      
int Max(T a[], int n)                    
{           
    int pos=0;                        
    for (int i=1; i<n; i++)                
       if (a[pos]<a[i])
          pos=i;
    return pos;
}

  关键操作是比较,一共进行了n-1次比较,所用时间复杂对为T(n)=n-1步。
  根据不同的程序与算法,关键操作数又分为最坏情况,最好情况以及平均情况(设每种情况概率相等并求数学期望),如下:

//在a[0:n-1]中搜索x,若找到则返回所在的位置,否则返回-1
template < class T >
int SeqSearch (T a[ ], const T &x, int n)
{ 
   int i;
   for (i=0; i<n && a[i]!= x; i++);
   if (i==n)  return -1;
   return i;
}

  最好情况:比较 1 次;
  最坏情况:比较 n 次;
  平均情况: 1 n + 1 ( n + ∑ i = 1 n i ) = n 2 + n n + 1 {1\over n+1}(n+\sum\limits_{i=1}^ni)={n\over 2}+{n\over n+1} n+11(n+i=1ni)=2n+n+1n
(能找到的有n种情况,遍历完找不到为一种情况,总共n+1种情况,每种概率为 1 n + 1 1\over n+1 n+11

引入渐进符号

  1. 时间复杂度的分析当输入规模n很大时才有意义,n趋向于无穷
  2. 输入规模很大时,只关心T(n)的阶,更加方便

  常用的渐进函数:1,logn,n,nlogn,n2,2n,n!
  渐近上界: f ( n ) = O ( g ( n ) ) f(n) = O(g(n)) f(n)=O(g(n)),存在正实数 c 和正整数 N, 使得当n>N时, f(n) ≤ c·g(n),重要的上界: n 2 n = O ( n ! ) n2^n=O(n!) n2n=O(n!)
  渐近下界: f ( n ) = Ω ( g ( n ) ) f(n) = Ω(g(n)) f(n)=Ω(g(n)),存在正实数 c 和正整数 N, 使得当n>N时,f (n) ≥ c·g(n)
  渐近同阶: f ( n ) = Θ ( g ( n ) ) f(n) =Θ(g(n)) f(n)=Θ(g(n)),函数g(n)既是f (n)的渐近上界又是f (n)的渐近下界。此时如果极限 l i m ( f ( n ) g ( n ) ) lim({f(n)\over g(n)}) lim(g(n)f(n))存在的话,应该是一个正实数。

f ( n ) f(n) f(n) g ( n ) g(n) g(n) f ( n ) = O ( g ( n ) ) f(n)=O(g(n)) f(n)=O(g(n)) f ( n ) = Ω ( g ( n ) ) f(n)=Ω(g(n)) f(n)=Ω(g(n)) f ( n ) = Θ ( g ( n ) ) f(n)=Θ(g(n)) f(n)=Θ(g(n))
2n3+3n100n2+2n+100FTF
50n+logn10n+loglognTTT
50nlogn10nloglognFTF
lognlog2nTFF
n!5nFTF

举例(只保留主项的阶):
  关键操作数为:n-1,则T(n)=n
         2(n-1),则T(n)=n


  按照渐进阶从低到高的顺序排列以下表达式:
   4 n 2 , l o g n , 3 n , 20 n , n 2 / 3 , n ! 4n^2,logn,3^n,20n,n^{2/3},n! 4n2logn3n20nn2/3n!
   l o g n &lt; n 2 / 3 &lt; 20 n &lt; 4 n 2 &lt; 3 n &lt; n ! logn &lt; n^{2/3} &lt; 20n &lt; 4n^2 &lt; 3^n &lt; n! logn<n2/3<20n<4n2<3n<n!
(logn永远小于nx,阶乘最大且n2n=O(n!),指数的上界是阶乘)

实例分析

  1)假设某算法在输入规模是 n 时为T(n) = 3 ∗ 2 n 3*2^n 32n。 在某台计算机上实现并完成该算法的时间是t 秒.现有另一台计算机,其运行速度为第一台的 64 倍, 那么,在这台计算机上用同一算法在t 秒内能解决规模为多大的问题?

  设原机器速度为(v步关键步数/s),则现在机器速度为64v,输入规模为n时,机器执行 3 ∗ 2 n 3*2^n 32n 步关键步数,用的时间为t,则有 3 ∗ 2 n v 3*2^n\over v v32n=t ,在新机器上则为, 3 ∗ 2 m 64 v 3*2^m\over 64v 64v32m=t ,连立俩个公式得,m=n+6,所以输入规模增大为 n+6。

  2)若上述算法改进后的新算法的时间复杂度为 T(n) = n 2 n^2 n2 , 则在新机器上用t 秒时间能解决输入规模为多大的问题?

  设输入规模为m,则时间复杂度为 T(m)= m 2 m^2 m2,新机器速度为64v,则 m 2 64 v m^2\over 64v 64vm2=t,又由上面得 3 ∗ 2 n v 3*2^n\over v v32n=t,连立得 m=8 3 ∗ 2 n \sqrt{3*2^n} 32n

  3)若进一步改进算法,最新的算法的时间复杂度为T(n) = 8,其余条件不变,在新机器上运行,在t 秒内能够解决输入规模为多大的问题?

  输入规模可以是任意大,因为无论输入多少,程序就运行8步关键步数,不随输入规模增大而增大。

复杂性了解

  由于当前设备越来越廉价,使得空间复杂度变得不那么重要,有时工程上为保证响应时间,常常是拿空间来换时间,所以对于时间复杂度的要求更重要。对于一个算法或问题明确其时间复杂度尤为重要,计算效率上甚至是可不可解都需要去明确,如指数时间复杂度问题,如果问题规模变大,则问题会变得不可解。
  如著名的旅行商问题(NP-hard),我们用时间复杂度来直观的阐释,设城市数量为n,旅行商问题的状态空间搜索树为一颗排列树,所以运算量的上限为O(n!),由于O(n!)=O(n× 2 n 2^n 2n),如果城市数量为100个,则100× 2 100 2^{100} 2100≈1.8 × 1 0 32 10^{32} 1032,我们用10亿次/秒的超级计算机来求解, 1.8 × 1 0 32 1 0 9 1.8 ×10^{32}\over 10^9 1091.8×1032=1.8 × 1 0 23 10^{23} 1023秒=5千7百万亿年,计算机运行一天也就只能解决41个城市。
  相对于多项式复杂度算法:快速排序 ( O ( n l o g n ) ) (O(nlogn)) (O(nlogn)) 10万个数据1.7毫秒就处理完,网络中的Dijkstra算法(O( n 2 n^2 n2))求解1万个顶点的单源最短路径问题0.1秒处理完,计算机是不怕O( n x n^x nx)复杂度,但对于无多项式算法的指数型问题是束手无策的,NP完全性理论就是用来揭示问题的难易程度。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值