数据结构和算法(一)复杂度分析

数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html)

数据结构和算法本身解决的是 "快" 和 "省" 的问题,即如何让代码运行得更快,如何让代码更省存储空间。所以,执行效率是算法一个非常重要的考量指标。那如何来衡量你编写的算法代码的执行效率呢?这里就要用:时间复杂度空间复杂度分析。

复杂度分析是整个算法学习的精髓,只要掌握了它,数据结构和算法的内容基本上就掌握了一半。

1. 时间复杂度

1.1 什么是时间复杂度

一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度。记为 T(n)。

在刚才提到的时间频度中,n 称为问题的规模,当 n 不断变化时,时间频度 T(n) 也会不断变化。但有时我们想知道它变化时呈现什么规律。为此,我们引入时间复杂度概念。

一般情况下,算法中基本操作重复执行的次数是问题规模 n 的某个函数,用 T(n) 表示,若有某个辅助函数 f(n),使得当 n 趋近于无穷大时,T(n) / f(n) 的极限值为不等于零的常数,则称 f(n) 是 T(n) 的同数量级函数。记作 T(n) = O(f(n)),称 O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度

  • 随着问题规模 n 的增大,常数部分的影响越来越小

    T(n) = 2n2 + 4n +log2n + 4

  • 随着问题规模 n 的増大,增长最快的项影响越来越大

    T(n) = 2n2 + 4n + log2n + 4

  • 渐进时间复杂度只关注增长最快的项

    T(n) = O(n2) // 去除常数系数,去除复杂度小的项

  • logn 一般表示 log2n

有时候,算法中基本操作重复执行的次数还随问题的输入数据集不同而不同,如在冒泡排序中,输入数据有序而无序,其结果是不一样的。此时,我们计算平均值。

1.2 时间复杂度分析

(1)只关注循环执行次数最多的一段代码

(2)加法法则:总复杂度等于量级最大的那段代码的复杂度

(3)乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积

实例 1: T(n) = 1 + n + 2n2 = O(n2)

sum = 0;                   // 执行 1 次
for(i = 1; i <= n; i++) // 执行 n 次
for(j = 1;j <= n;j++) // 执行 n^2 次
sum++; // 执行 n^2 次

实例 2:T(n) = 1 + 4n = O(n)

a = 0;  b= 1;                // 执行 1 次
for (i = 1; i <= n; i++) { // 执行 n 次
s = a + b; // 执行 n 次
b = a; // 执行 n 次
a = s; // 执行 n 次
}

实例 3:T(n) = O(log2n)

i = 1;            // 执行 1 次
while (i <= n)
i = i * 2; // 设频度是 f(n),则:2^f(n)<=n; f(n)<=log2n

1.3 常见的时间复杂度

虽然代码千差万别,但是常见的复杂度量级并不多。我稍微总结了一下,这些复杂度量级几乎涵盖了你今后可以接触的所有代码的复杂度量级。对于以下复杂度量级,可以粗略地分为两类,多项式量级和非多项式量级。其中,非多项式量级只有两个:O(2n) 和 O(n!),执行效率也非常低。

  1. 常量阶 O(1)
  2. 对数阶 O(logn)
  3. 线性阶 O(n)
  4. 线性对数阶 O(nlogn)
  5. 平方阶 O(n2) O(n3) O(n4)
  6. 指数阶 O(2n):不常见
  7. 阶乘阶 O(n!):不常见

常见的算法的时间复杂度之间的关系为:

O(1) < O(logn) < O(n) < O(nlogn) < O(n2) < O(2n)<O(n!) < O(nn)

1.4 主定律

1.5 最好、最坏、平均、均摊时间复杂度

  1. 最好情况时间复杂度:代码在最坏情况下执行的时间复杂度。(少使用)
  2. 最坏情况时间复杂度:代码在最理想情况下执行的时间复杂度。(少使用)
  3. 平均时间复杂度:用代码在所有情况下执行的次数的加权平均值表示。(少使用)
  4. 均摊时间复杂度:在代码执行的所有复杂度情况中绝大部分是低级别的复杂度,个别情况是高级别复杂度且发生具有时序关系时,可以将个别高级别复杂度均摊到低级别复杂度上,也叫摊还算法。(极少使用)

下面以一段代码示例,对上述 4 个概念进行简单的分析。

int arr[] = new int[10];
int len = 10;
int i = 0; void add(int element) { // 插入元素时,如果空间不够,先扩容再插入
if (i >= len) {
int newArr[] = new int[len * 2];
for (int j = 0; j < len; ++j) {
newArr[j] = arr[j];
}
arr = newArr;
len = 2 * len;
}
arr[i] = element;
++i;
}

上述示例:最好是 O(1),最坏是O(n),平均和均摊都是O(1)。

摊还算法分析,执行 n 次 O(1) 插入后会执行一次 O(n) 插入,那么我们可以将这次 O(n) 插入公摊到 n 次操作上,这样均摊后仍是 O(1)。

个人体会:平均和平摊基本就是一个概念,平摊是特殊的平均。在分析时间复杂度是 O(1) 还是 O(n) 的时候最简单就是凭感觉,出现 O(1) 的次数远大于出现 O(n) 出现的次数,那么平均平摊时间复杂度就是O(1)。

2.2 空间复杂度

空间复杂度:算法所需存储空间的度量,记作: S(n) = O(f(n)),其中 n 为问题的规模。

我们常见的空间复杂度就是 O(1)、O(n)、O(n2),像 O(logn)、O(nlogn) 这样的对数阶复杂度平时都用不到。如下代码空间复杂度 O(n)。

int i = 0;                     // 申请空间大小为 1
int[] arr = new int[n]; // 申请空间大小为 n 的数组
for (i; i < n; i++) {
arr[i] = i;
}

一个算法在计算机存储器上所占用的存储空间,包括存储算法本身所占用的存储空间,算法的输入输出数据所占用的存储空间和算法在运行过程中临时占用的存储空间这三个方面。如果额外空间相对于输入数据量来说是个常数,则称此算法是原地工作。

算法的输入输出数据所占用的存储空间是由要解决的问题决定的,是通过参数表由调用函数传递而来的,它不随本算法的不同而改变。存储算法本身所占用的存储空间与算法书写的长短成正比,要压缩这方面的存储空间,就必须编写出较短的算法。


每天用心记录一点点。内容也许不重要,但习惯很重要!

Java数据结构和算法(一)概念的更多相关文章

  1. Java数据结构和算法(一)——简介

    本系列博客我们将学习数据结构和算法,为什么要学习数据结构和算法,这里我举个简单的例子. 编程好比是一辆汽车,而数据结构和算法是汽车内部的变速箱.一个开车的人不懂变速箱的原理也是能开车的,同理一个不懂数 ...

  2. Java数据结构和算法(二)——数组

    上篇博客我们简单介绍了数据结构和算法的概念,对此模糊很正常,后面会慢慢通过具体的实例来介绍.本篇博客我们介绍数据结构的鼻祖——数组,可以说数组几乎能表示一切的数据结构,在每一门编程语言中,数组都是重要 ...

  3. Java数据结构和算法 - 堆

    堆的介绍 Q: 什么是堆? A: 这里的“堆”是指一种特殊的二叉树,不要和Java.C/C++等编程语言里的“堆”混淆,后者指的是程序员用new能得到的计算机内存的可用部分 A: 堆是有如下特点的二叉 ...

  4. Java数据结构和算法 - 二叉树

    前言 数据结构可划分为线性结构.树型结构和图型结构三大类.前面几篇讨论了数组.栈和队列.链表都是线性结构.树型结构中每个结点只允许有一个直接前驱结点,但允许有一个以上直接后驱结点.树型结构有树和二叉树 ...

  5. Java数据结构和算法 - 递归

    三角数字 Q: 什么是三角数字? A: 据说一群在毕达哥拉斯领导下工作的古希腊的数学家,发现了在数学序列1,3,6,10,15,21,……中有一种奇特的联系.这个数列中的第N项是由第N-1项加N得到的 ...

  6. Java数据结构和算法 - OverView

    Q: 为什么要学习数据结构与算法? A: 如果说Java语言是自动档轿车,C语言就是手动档吉普.数据结构呢?是变速箱的工作原理.你完全可以不知道变速箱怎样工作,就把自动档的车子从1档开到4档,而且未必 ...

  7. Java数据结构和算法 - 什么是2-3-4树

    Q1: 什么是2-3-4树? A1: 在介绍2-3-4树之前,我们先说明二叉树和多叉树的概念. 二叉树:每个节点有一个数据项,最多有两个子节点. 多叉树:(multiway tree)允许每个节点有更 ...

  8. Java数据结构和算法(一)线性结构

    Java数据结构和算法(一)线性结构 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 线性表 是一种逻辑结构,相同数据类型的 ...

  9. Java数据结构和算法(一)树

    Java数据结构和算法(一)树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 前面讲到的链表.栈和队列都是一对一的线性结构, ...

  10. Java数据结构和算法(四)赫夫曼树

    Java数据结构和算法(四)赫夫曼树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 赫夫曼树又称为最优二叉树,赫夫曼树的一个 ...

随机推荐

  1. 知乎日报 API的图片盗链问题

    由最近 基于vue的知乎日报单页应用 引发的问题 以及问题解决历程 通过 知乎日报API 基于vue做一个知乎日报的单页应用,在获取图片时存在一个图片盗链问题,图片无法加载 提示 403 错误, 最终 ...

  2. CentOS7.3下yum练手安装Nginx,支持php5.4

    yum install php php-devel 安装的是5.4 那么安装完毕了,怎么设置nginx和php 解析 1 添加nginx 默认主页index.php  vim .../etc/ngin ...

  3. centos7配置vsftpd服务器

    参考网站:https://blog.csdn.net/lianghongge/article/details/78209445 ==================================== ...

  4. 解决python执行linux查看文件命令后,因为^@特殊符号导致部分内容不显示的问题

    问题现象 文件a的内容如下: 查看第3行到第5行的内容:sed -n '3,5p' /tmp/test/a 可见在命令行执行,是没有问题的. 在python中使用paramiko模块执行linux命令 ...

  5. java 项目中类找不到异常解决办法

    最后点击Apply and Close就可以了

  6. javaScript日期

    日历 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"> <html> <head> <t ...

  7. 数据库的 ACID 属性

    ACID(Atomicity 原子性.Consistency 一致性.Isolation 隔离性.Durability 持久性)是一系列属性. 这些属性保证了数据库事物的可靠.在数据库中,对数据的一系 ...

  8. PHP函数注释规范

    <?php/*** @name 名字* @abstract 申明变量/类/方法* @access 指明这个变量.类.函数/方法的存取权限* @author 函数作者的名字和邮箱地址* @cate ...

  9. UI5-文档-2.5-开发混合Web容器

    开发混合Web容器 您可以将移动应用程序开发为混合应用程序,该混合应用程序由本机应用程序包装程序(例如PhoneGap)和HTML查看器组成,用于在用户界面上显示内容. 混合应用程序的优点是可以在应用 ...

  10. Haskell语言学习笔记(44)Lens(2)

    自定义 Lens 和 Isos -- Some of the examples in this chapter require a few GHC extensions: -- TemplateHas ...