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

数据结构与算法目录(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. tcp协议和udp协议的使用场景

      一:什么是TCP(Transmission Control Protocol,传输控制协议) tcp是面向连接的协议,也就是说,在收发数据前,必须和对方建立可靠的连接.一个TCP连接必须要经过三次 ...

  2. 34. CentOS-6.3安装配置Apache2.2.6

    安装说明 安装环境:CentOS-6.3安装方式:源码编译安装 软件:httpd-2.2.6.tar.gz  | pcre-8.32.tar.gz | apr-1.4.6.tar.gz | apr-u ...

  3. XMLTransformProvider

    XMLTransformProvider1 XMLTransformProvider1.TransformRead.SourceXmlDocument := XMLDoc.GetDOMDocument ...

  4. 怎样在本地windows安装和配置zookeeper

    Zookeeper是什么?有什么用? Zookeeper是一个分布式协调服务. 作用:为用户的分布式应用程序提供协调服务.  zookeeper在底层其实只提供了两个功能: 1.管理(存储,读取)用户 ...

  5. 格式与布局 float 左右悬浮边框

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. Servlet Filter 过滤器 对指定页面不拦截

    package niit.dxs.controller; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; i ...

  7. EasyUI 删除

    <script type="text/javascript"> <!-- js --> /*================================ ...

  8. SSL原理分析

    SSL协议的工作流程: 服务器认证阶段:       1)客户端向服务器发送一个开始信息“Hello”以便开始一个新的会话连接:      2)服务器根据客户的信息确定是否需要生成新的主密钥,如需要则 ...

  9. 网站发布时候,图片,css,js等都不显示

    因为IIS里面的MIME类型没有添加,就是安装IIS时候没有勾选对.需要重新勾选,安装IIS.

  10. 如何用INNO安装添加快捷启动方式到Win7的快速启动栏(超级任务栏)

    问题:如何用INNO安装添加快捷启动方式到Win7的快速启动栏(超级任务栏) 在XP下,添加方式是直接把快捷方式复制到%appdata%\Microsoft\Internet Explorer\Qui ...