贯穿算法始终的复杂度分析

贯穿算法始终的复杂度分析

前言

对于数据结构与算法,我们首先给出一个宽泛的定义:

从广义上来说,数据结构是一组数据的存储结构,算法是操作数据的一组方法。从狭义上来说,数据结构与算法是那些为人所知的解决方案,比如队列,堆,栈,二分查找,动态规划等。

那么数据结构与算法之间又是怎样的藕断丝连呢?

一言以蔽之,数据结构是为算法服务的,算法要作用在特定的数据结构之上,也就是它们之间是相互依存的,不能孤立算法去谈数据结构。

复杂度分析

数据结构和算法本身解决的是快和省的问题,也就是说时间和空间上的执行效率是衡量算法的指标,为了更直观的评估这项指标,就需要量化其复杂度的表示,即引入大O复杂度表示法

大O复杂度表示法

我们不再推导理论,而是直接给出一个非常重要的规律,即:

代码的执行时间T(n)与每条代码的执行次数n成正比,这里的先决条件是假定每行代码执行的时间相同(即取指,译码,执行的过程)

再将这个规律总结成公式,就可以得到:
T ( n ) = O ( f ( n ) ) T(n) = O(f(n)) T(n)=O(f(n))
这里的n表示的是数据的规模,T(n)是代码的执行时间,f(n)是每行代码执行的次数总和,大O表示的是一种函数关系,即T(n)与f(n)成正比,

  • 这里需要注意的是,大O实际上并不表示代码的总执行时间,而指的是代码执行时间随着数据规模增长的变化趋势,简称时间复杂度

既然时间复杂度仅表征一种变化趋势,那在时间复杂度评估时,就可以忽略一些对于变化趋势没有影响的因素,比如低阶,常量,系数,我们只关注循环执行次数最多的代码就行了。

常见的复杂度并不多,从低阶到高阶包括:O(1),O(logn),O(n),O(nlogn),O(n2)——

image-20210202162842192

  • 图来自数据结构与算法之美专栏

对应于快和省的需求,复杂度分析有两个维度,时间复杂度空间复杂度,先来看时间复杂度——

时间复杂度

将时间复杂度细分,可以分为四类:最好情况时间复杂度,最坏时间复杂度,平均时间复杂度,均摊时间复杂度。我们逐一来看——

最好时间复杂度:即在最理想的情况下,执行这段代码的时间复杂度。

最坏时间复杂度:即在最糟糕的情况下,执行这段代码的时间复杂度。

平均时间复杂度:即将每种可能情况下的执行次数加和再除以可能发生的情况总数,可以理解为概率论中的期望时间复杂度,即加权平均值

均摊时间复杂度:即是有规律的加权平均值,是平均时间复杂度分析的特例,当遇到具体案例时,我们再介绍。

空间复杂度

空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度,记做S(n)=O. (f(n))。

这里需要注意的是,往往我们会将一段代码中为存储元素时所申请的内存空间认为是空间复杂度,这是一种错误的认知,这段内存是固有的,而我们需要评估的是执行过程中占有空间随着执行总行数的变化趋势,它体现的是一个动态的值。

小练习

我们来判断下面这段代码的最好时间复杂度,最坏时间复杂度,均摊时间复杂度:

// 全局变量,大小为10的数组array,长度len,下标i。
int array[] = new int[10]; 
int len = 10;
int i = 0;

// 往数组中添加一个元素
void add(int element) {
   if (i >= len) { // 数组空间不够了
     // 重新申请一个2倍大小的数组空间
     int new_array[] = new int[len*2];
     // 把原来array数组中的数据依次copy到new_array
     for (int j = 0; j < len; ++j) {
       new_array[j] = array[j];
     }
     // new_array复制给array,array现在大小就是2倍len了
     array = new_array;
     len = 2 * len;
   }
   // 将element放到下标为i的位置,下标i加一
   array[i] = element;
   ++i;
}

显然,最快时间复杂度的情况是数组空间足够,直接将其存储在下标为i的内存空间中,复杂度为O(1),最坏的情况即是数组已满,需要扩容长度为len*2的空间,复杂度为O(n)。我们可以认为需要扩容的概率为1/n+1.而不需要扩容的概率是n/n+1,需要扩容的复杂度n均摊到不需要扩容的n种情况,即可得到均摊时间复杂度为O(1).

日拱一卒,功不唐捐。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值