算法入门Study(一)

一、时间复杂度

1.1 概念

时间复杂度分析统计的不是算法运行时间,而是算法运行时间随着数据量变大的趋势

特点:

1.能够有效评估算法效率。 2.推算方法更简便。 3.存在一定局限性。

1.2 函数渐进界

函数渐进上界(最差时间复杂度)

复杂度由T(n)中最高的项来决定,忽略常数项、T(n)中的各种系数,使用大O记号表示。最实用,因为给出了一个效率安全值。

函数渐进下界(最佳时间复杂度)

Ω记号表示

平均时间复杂度

体现算法在随机输入数据下的运行效率,用Θ表示

1.3 常见类型

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

常数阶 < 对数阶 < 线性阶 < 线性对数阶 < 平方阶 < 指数阶 < 阶乘阶

二、空间复杂度

2.1 概念

空间复杂度衡量算法占用内存空间随着数据量变大的增长趋势

算法相关空间:

输入空间:输入数据

暂存空间:暂存数据、栈帧空间、指令空间(统计范围)

输出空间:输出数据(统计范围)

2.2 推算方法

(1)以最差输入数据为准

(2)以算法运行中的峰值内存为准

2.3 常见类型

O(1) < O(logn) < O(n) < O(n2) < O (2n)

常数阶 < 对数阶 < 线性阶 < 平方阶 < 指数阶

三、数据与链表

3.1 概念

数组是一种线性数据结构,存储数组的内存空间是连续的,而链表的内存空间则无须连续

元素内存地址 = 数组内存地址(首元素) + 元素长度 * 元素索引

索引本质上是内存地址的偏移量

快速排序、归并排序、二分查找等都在数组上进行

在大多数编程语言中,数组的长度是不可变的

3.2 数组插入删除缺点

平均时间复杂度均为O(n),n为数组长度

超出数组范围的元素会丢失,会造成部分内存空间的浪费

3.3 数组优点与局限性

支持随机访问,且时间复杂度是O(1)

提升后续操作的执行速度

分配连续内存块,无需额外的结构开销

3.4 链表适用性

数组非常大,内存无法提供大的连续空间

每个元素都是一个节点对象,每个节点通过“引用”相连接,引用记录下一个节点的内存地址,使其访问

3.5 链表概念

链表的储存空间是分散的,而不是连续的

链表的组成单位是Node对象,包含两项数据:节点的值和指向下一节点的引用

首个节点被称为“头节点”,最后一个节点为“尾节点”,尾节点指向的是空(None、null、nullptr)

3.6 节点操作

初始化链表—-将头节点当作链表的代称

插入节点—-改变两个节点的引用(指针),时间复杂度为O(1)

删除节点—-改变一个节点的引用(指针)

访问节点—-访问链表的第i个节点需要循环 i - 1轮,时间复杂度为O(n),效率较低

3.7 常见链表类型

  • 单向链表
  • 环形链表(首尾相连),任意节点可视为头节点
  • 双向链表,朝两个方向遍历链表,需要占用更多的内存空间

总结:

数组 链表
存储方式 连续内存空间 分散内存空间
容量扩展 长度不可变 可灵活拓展
内存效率 占用内存少、浪费部分空间 占用内存多
访问元素 O(1) O(n)
添加元素 O(n) O(1)
删除元素 O(n) O(1)
0%