时间复杂度(2)

时间复杂度

我们常需要描述特定算法相对于 n(输入元素的个数 )需要做的工作量。在一组未排序的数据中检索,所需的时间与 n成正比;如果是对排序数据用二分检索,花费的时间正比于 logn。排序时间可能正比于 n2或者nlogn。

我们希望能够比较算法的运行时间和空间要求,并使这种比较能与程序设计语言、编译系统、机器结构、处理器的速度及系统的负载等复杂因素无关。

为了这个目的,人们提出了一种标准的记法,称为“大O记法”.在这种描述中使用的基本参数是 n,即问题实例的规模,把复杂性或运行时间表达为 n的函数 。这里的“O”表示量级 (order),比如说“二分检索是 O(logn)的”,也就是说 它需要“通过logn量级的步骤去检索一个规模为n的数组”记法 O ( f(n) )表示当 n增大时,运行时间至多将以正比于 f(n)的速度增长。这种渐进估计对算法的理论分析和大致比较是非常有价值的,但在实践中细节也可能造成差异。例如,一个低附加代价的 O(n2)算法在n较小的情况下可能比一个高附加代价的 O(nlogn)算法运行得更快。当然,随着n足够大以后,具有较慢上升函数的算法必然工作得更快。

 

   
   
Temp = i;
i
= j;
j
= temp;
                   

 

以上三条单个语句的频度均为1,该程序段的执行时间是一个与问题规模n无关的常数。算法的时间复杂度为常数阶,记作T(n)=O(1)。如果算法的执行时 间不随着问题规模n的增加而增长,即使算法中有上千条语句,其执行时间也不过是一个较大的常数。此类算法的时间复杂度是O(1)。

例 2.1. 交换i和j的内容

1 ) sum = 0 ;             (一次)
2 )  for (i = 1 ;i <= n;i ++ )   (n次 )
3 )     for (j = 1 ;j <= n;j ++ ) (n ^ 2次 )
4 )         sum ++ ;       (n ^ 2次 )


解:T(n)
= 2n ^ 2 + n + 1   = O(n ^ 2 )

例 2.2.  

   
   
for  (i = 1 ;i < n;i ++ )
{
 y
=y+1;        ①
 
for (j=0;j<=(2*n);j++)
    x
++;           ②
}
          



解:语句1的频度是n-1, 语句2的频度是(n-1)*(2n+1)=2n^2-n-1.
f(n)=2n^2-n-1+(n-1)=2n^2-2,该程序的时间复杂度T(n)=O(n^2).

例 2.3. 

a = 0 ;b = 1 ;      ①
for  (i = 1 ;i <= n;i ++ ) ②
{
  s
=a+b;    ③  
  b
=a;     ④
  a
=s;     ⑤
}



解:语句1的频度:
2 ,        语句2的频度: n,        语句3的频度: n - 1 ,        语句4的频度:n - 1 ,    
语句5的频度:n
- 1 ,                                  则:T(n) = 2 + n + 3 (n - 1 ) = 4n - 1 = O(n).



例 2.4.

 

i=1;       ①
while (i<=n)
i=i*2; ②

解:语句1的频度是1,        设语句2的频度是f(n),        则:2^f(n)<=n;f(n)<=log2n    
取最大值f(n)= log2n,则该程序的时间复杂度T(n)=O(log2n )

 

例 2.5. 

   
   
for (i = 0 ;i < n;i ++ )
{
  
for(j=0;j<i;j++)
  
{
    
for(k=0;k<j;k++)
      x
=x+2;
  }

}



解:当i
= m, j = k的时候,内层循环的次数为k
当i
= m时, j 可以取  0 , 1 ,...,m - 1  ,  所以这里最内循环共进行了0 + 1 + ... + m - 1 = (m - 1 )m / 2次
所以,i从0取到n, 则循环共进行了: 
0 + ( 1 - 1 ) * 1 / 2 + ... + (n - 1 )n / 2 = n(n + 1 )(n - 1 ) / 6
所以时间复杂度为O(n
^ 3 ).

我们还应该区分算法的最坏情况的行为和期望行为。如快速排序的最 坏情况运行时间是 O(n^2),但期望时间是 O(nlogn)。通过每次都仔细 地选择基准值,我们有可能把平方情况 (即O(n^2)情况)的概率减小到几乎等于 0。在实际中,精心实现的快速排序一般都能以 (O(nlogn)时间运行。

下面是一些常用的记法:



访问数组中的元素是常数时间操作,或说O(1)操作。一个算法如 果能在每个步骤去掉一半数据元素,如二分检索,通常它就取 O(logn)时间。用strcmp比较两个具有n个字符的串需要O(n)时间 。常规的矩阵乘算法是O(n^3),因为算出每个元素都需要将n对 元素相乘并加到一起,所有元素的个数是n^2。

指数时间算法通常来源于需要求出所有可能结果。例如,n个元 素的集合共有2n个子集,所以要求出所有子集的算法将是O(2n)的 。指数算法一般说来是太复杂了,除非n的值非常小,因为,在 这个问题中增加一个元素就导致运行时间加倍。不幸的是,确实有许多问题 (如著名 的“巡回售货员问题” ),到目前为止找到的算法都是指数的。如果我们真的遇到这种情况, 通常应该用寻找近似最佳结果的算法替代之。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值