算法复杂度(几种常见算法求法总结)
1.什么是时间复杂度
概念:算法的时间复杂度是一个函数,算法中的基本操作的执行次数,为算法的时间复杂度。实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要大概执行次数,那么这里我们使用大O的渐进表示法。
推导大O阶方法:
1、用常数1取代运行时间中的所有加法常数。
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。
在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)
特殊情况:对递归来说,时间复杂度是单次递归乘上总的递归次数
2.什么是空间复杂度
在这个算法当中,函数创建的变量(对象)的个数关于问题规模N的数学表达式.
注意:函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因
此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。
特殊情况:单次递归乘上递归深度(递归深度不是递归次数)
一般常见的空间复杂度有:O(N) O(1) O(N^2)
3.复杂度的考察方式
1.二分查找
因为二分查找每次排除掉一半的不适合值,所以对于n个元素的情况:
一次二分剩下:n/2
两次二分剩下:n/2/2 = n/4
…
m次二分剩下:n/(2^m)
在最坏情况下是在排除到只剩下最后一个值之后得到结果,即
n/(2^m)=1
所以由上式可得 : 2^m=n
进而可求出时间复杂度为: log2(n)
2.各种排序的时间空间复杂度
3.实现一个算法,有时间空间复杂度的要求
4.按照特定时间空间复杂度对算法进行优化
线性表之顺序表
1.什么是顺序表?
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改.
2.顺序表分类
顺序表一般可以分为:
- 静态顺序表:使用定长数组存储元素。
- 动态顺序表:使用动态开辟的数组存储。
直接的区别在于:动态顺序表的底层空间是从堆上申请的.
3.顺序表基本操作(各种接口的实现)(待完善)
这部分内容专门写了博客,这里不写了.
4.顺序表的缺点
- 中间/头部的插入删除,时间复杂度为O(N)
- 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
- 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们
再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。
5.顺序表的oj题
顺序表之链表
1.什么是链表
概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。
2.链表分类
一共八种分类:是否带头 单双向 是否循环
主要掌握:
1.不带头的单链表(面试常考)
2.带头双向循环链表(实际常用,c++标准库就提供这类链表)
3.链表常见oj题
单链表的逆置(非常非常常考)
求链表的中间节点(要求只能遍历一次)
求倒数第k个节点