| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> 数据结构第一步(复杂度分析) -> 正文阅读 |
|
[数据结构与算法]数据结构第一步(复杂度分析) |
目录 算法什么是算法?
算法复杂度复杂度用来衡量一个算法执行效率好与坏,复杂度又被分为了两个维度去分析,一个是时间复杂度,另一个是空间复杂度。
纠正一个小误区:时间复杂度并不代表一个算法的执行时间,仅代表了一个算法的执行效率。因为执行时间是无法被精准的衡量的,执行时间可能会受到硬件等因素的影响,有时会快有时会慢,所以是无法通过时间的角度去衡量一个算法的优劣。 大O的渐进表示法“大O的渐进表示法”就是把算法的执行时间或占用空间的一个增长趋势,将代码所有步骤转换成一个以数据N为参数的数学函数。 根据上图推导出公式 : N*N + 2*N +10
可以发现,当N无限大的时候,后两项的2*N+10其实已经对最终的计算结果影响不大了,所以可以几乎忽略不计。比如一个亿万富翁,在酒店给了服务生两百块钱,这两百块钱站在富翁的角度,两百块钱对富翁资产产生的动摇微乎其微,几乎可以忽略不计。所以这里也一样,可以直接去抓大头,只取对结果影响最大的N*N,忽略掉对结果影响不大的项。所以大O的渐进表示法也只是去大概的估算一个算法的执行次数,这里用大O表示法可以表示为O(N^2)。 所以,大O的渐进表示法讨论的不是算法具体的一个执行次数,只讨论这个算法处于哪一个量级。 推导大O阶的方法:
时间复杂度分析一、冒泡排序时间复杂度
注意:并不是两层循环就是N^2 、三层循环就是N^3、N层循环就是N^N,具体还要看程序的具体实现逻辑。 二、二分查找时间复杂度
假设数组长度为N,找了X次,那么N = N/2/2/2.../2 = 1时结束。然后表达式逆推一下等于1乘以X个2。 最后求得 log以2为底N 的对数,所以二分查找最坏的时间复杂度就是O(log?N)。
三、N的阶乘时间复杂度阶乘不存在最好和最坏的情况。 要理解递归,最好先画递归的展开图: ?可以发现N = 6时,除去第一次不是递归总共递归了6次,那么N的阶乘的时间复杂度就是O(N)。 如果对这个函数进行了个改造,在里加上一个N层循环,那么时间复杂度就变成O(N^2),所以递归不能只看递归了多少次,也还要计算下递归内部的实际执行次数。 ?四、递归的斐波那契数列时间复杂度用递归实现的斐波那契数列,用递归展开来就是下面这样。 可以把递归分为N层,当递归1层时就有2^0,2层2^1,3层2^2....在第N层时就递归了2^N-1次,也就是2的N-1次方,假设N = 100,就要递归2^100,效率非常的低,斐波那契的递归展开图,就类似于一颗二叉树。它的时间复杂度是O(2^N) ?五、有两个未知数的时间复杂度因为我们不能确定两个未知数谁大谁小的情况下,我们只能让两个未知数相加起来,那么时间复杂度就是O(N+M)。但是如果题目有说M远大于N或者是N远大于M时,就可以写成O(M) 或者 O(N)。 空间复杂度分析一、冒泡排序空间复杂度冒泡排序,这个算法并没有开辟额外的空间,也就是空间是常数次,它的空间复杂度就是O(1)。有些同学对exchange可能会有些存疑,每次循环都会创建一个exchange,为什么不是O(N)呢? exchange每次在第二层循环执行完之后生命周期结束被销毁,当回到第一层循环时,再创建的exchange其实与上一次的exchange使用的其实是同一块地址空间。 二、额外空间
三、N的阶乘空间复杂度N的阶乘,从之前的递归展开图就可以看出,如果算上第一次,总共调用了N+1次函数栈帧,但是忽略常数项就是O(N),那么它的空间复杂度就是O(N)。 四、斐波那契空间复杂度斐波那契的时间复杂度是O(2^N),那它的空间复杂度是多少呢?如果是光看递归展开图还真不能一眼就看出。这里就用动图来演示: 当N-1的栈帧被销毁后,函数会去调用N-2的栈帧,但是我要说的是,N-2使用的函数栈帧其实就是N-1销毁后还给操作系统的那块空间,证明一下: 可以证明一件事,时间一去不复返,空间可以重复利用,那么斐波那契在递归中调用空间调用了N层的栈帧,那么就使用了N个空间,它的空间复杂度其实就是O(N)。 空间复杂度通常都是O(N)或者O(1),很少碰到像O(N^2)或者O(2^N),(O(2^N)可以说几乎碰不到,因为实在是太大了,栈根本顶不住)。 常见复杂度的对比?可以看出O(logN)和O(1)几乎就是一条线,非常的快,O(N)线性的增长,再次是O(N*longN),到O(N^2)其实就已经非常慢了,20次就已经执行了400次。最慢的是N的阶乘O(N!)。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 9:49:34- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |