数据结构与算法分析

数据结构与算法学习-复杂度分析

2019-03-03  本文已影响24人  青争哥哥_

前言

这一篇笔记主要记录总结了什么是算法复杂度?、为什要做算法复杂度分析?、如何做算法复杂度分析?、常用的复杂度级别?以及如何掌握复杂度分析?等问题。

算法复杂度分析是什么?

数据结构与算法解决的是如何更省、更快的存储和处理数据的问题。因此就需要一个考量效率和资源消耗的方法,这就是复杂度分析方法。

复杂度也叫渐进复杂度,其中包含时间复杂度空间复杂度两个维度,是用来分析算法执行时间(或者占用空间)数据规模的增长关系,可以粗略的表示,越高阶复杂度的算法,执行效率越低。

为什么要做算法复杂度分析?

  1. 统计、监控等事后统计法的局限性:

    1. 测试结果高度依赖测试环境
    2. 测试结果受数据规模影响很大
  2. 因此需要一个不用具体的测试数据就可以粗略地估计算法的执行效率的方法。复杂度分析不依赖执行环境、成本低、可操作性强。

  3. 掌握复杂度分析,将能写出性能更优的代码。

如何做算法复杂度分析?

大 O 复杂度表示法

image

算法复杂度分析法则

  1. 只关注循环执行次数最多的一段代码
  2. 加法法则:总复杂度等于量级最大的那段代码的复杂度
  3. 乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积

空间复杂度分析

类比时间复杂度,空间复杂度全称就是渐进空间复杂度,表示算法的存储空间数据规模之间增长关系

常见的空间复杂度是:O(1)、O(n)、O(n^2)

最好、最坏时间复杂度

对有些代码,其复杂度有不是固定的,有最好、最坏的情况。如数组元素查找,有可能第一次就找到,这个时候算法时间复杂度是常数阶O(1),也有可能需要整个遍历一遍数组才能找到,这个时候是最坏的时间复杂度O(n)。

平均情况复杂度

由于最好和最坏情况复杂度对应的都是极端情况下的代码复杂度,发生的概率并不大,所以需要引入平均情况复杂度来更好的表示算法的时间复杂度。

平均情况复杂度 是将各种情况下时间复杂度发生的概率考虑进去,然后计算整体时间复杂度的期望值,所以平均情况复杂度也叫做加权平均时间复杂度或者期望时间复杂度

很多时候,只要使用一个复杂度就可以满足需求了。只有同一块代码在不同情况下,时间复杂度有量级的差距,才会使用这三种复杂度表示法来区分。

均摊时间复杂度

适用场景:对一个数据结构进行一组连续操作中,大部分情况下时间复杂度都很低,只有个别情况下时间复杂度比较高,而且这些操作之间存在前后连贯的时序关系,这个情况下,就可以将这一组操作放在一起分析,看能否将较高时间复杂度的那次操作平摊到其他那些时间复杂度较低的操作上。一般在能够应用均摊时间复杂度的场景,均摊时间复杂度就等于最好情况时间复杂度

分析方法:摊还分析

常用的算法复杂度级别

image image

如何掌握复杂度分析

多练习。

课后问题

1. 项目之前都会进行性能测试,再做代码的时间复杂度、空间复杂度分析是不是多次一举?

解答:不是多此一举,渐进时间,空间复杂度分析为我们提供了一个很好的理论分析的方向,成本低,可操作性强,不用具体的测试数据就可以粗略地估计算法的执行效率,有助于写出性能高效的代码,同时培养起算法复杂度分析的思维,可以和性能测试相辅相成。

2. 分析以下代码的复杂度

// 全局变量,大小为 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;
}

解答:


分享个人技术学习记录和跑步马拉松训练比赛、读书笔记等内容,感兴趣的朋友可以关注我的公众号「青争哥哥」。

image
上一篇下一篇

猜你喜欢

热点阅读