数据结构(三)复杂度的深层次剖析

之前发布了数据结构(一),很多同学反响不够清晰,那今天就发一篇对复杂度专题的博客,希望对大家理解复杂度提供一些帮助。

时间复杂度

我们先来一个理解一个复杂度,二分查找的复杂度(之前写过二分查找的专题博客,感兴趣的可以看一看)    CSDNicon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/135742310

我们在数据结构(一)中讲解了,但是没有画图,现在为了方便大家的理解现在我重新讲解一下。

我们先把代码拿出来看看

// 计算BinarySearch的时间复杂度?
int BinarySearch(int* a, int n, int x)
{
assert(a);
int begin = 0;
int end = n-1;
// [begin, end]:begin和end是左闭右闭区间,因此有=号
while (begin <= end)
{
int mid = begin + ((end-begin)>>1);
if (a[mid] < x)
begin = mid+1;
else if (a[mid] > x)
end = mid-1;
else
return mid;
}
return -1;
}

这时候大家会好奇该如何计算其复杂度,其实搞清楚原理也比较容易理解。

二分查找的原理就不在过多的讲解了,不懂的小伙伴可以去看看上面的链接。

我们还是老样子画图来为大家演示:

当我们在不断地缩减,直到缩减到只剩下一个值的时候。

那么这就是最坏的一个情况,如果这个值是我们想要找的那个值,那么就找到了,如果不是那么我们输出找不到。

随之而来的疑问就是,我们一共找了多少次呢?

假设我们有N个值,我们每次都缩减一半,那么就是N/2,这是一次。那么我们一共找了多少次呢?

N/2/2/2/2/2/2.............=1 直到我们找到那个数为止。  这是最坏情况,那么我们除了多少个2呢?

不难看出,其实我们找了多少次就除了多少个2。

关键点拨:假设我找了X次,那么我们 就可以得到表达式。

第一步:N/2/2/2/2/2/2/2...............=1

第二步:N=1*2^x  (等式两边同时乘2)

第三步:2^x=N

第四步:化简

基本操作执行最好1次,最坏O(logN)次,时间复杂度为 O(logN) ps:logN在算法分析中表示是底
数为2,对数为N。有些地方会写成logN 。(由于对数在键盘中不好敲出来,所以我们通常省略2)。

补充时间复杂度例题:

// 计算阶乘递归Fac的时间复杂度?
long long Fac(size_t N)
{
if(0 == N)
return 1;
return Fac(N-1)*N;
}

大家看到这串代码时一定有想骂街的冲动,但是有我在大家不用担心,我来为大家搞定它。

那么开始进入正题:

上面的代码是 N 的阶乘的原码,之前我的博客也写过,感兴趣的小伙伴可以去看看地址就放在这里了-用C语言实现阶乘的相加-CSDN博客文章浏览阅读373次,点赞11次,收藏9次。i=3 ret=1*2*3 此时的ret=6 可以理解为1*2*3。i=2 ret=1*2 此时ret=2 可以理解为1*2。当n=2时ret=1*2 同样把值存在sum中 此时的ret=2。ret开始变化 例如:当for循环运行到i=3时,i=1 ret=1*1 此时ret=1。那么我们有没有其他方案呢,答案是有的我们可以这样在求2的阶乘时直接在1的阶乘上乘2 1*2。关键点拨:ret=ret*n 当n=1时ret=1*1 并把值存在sum中。https://blog.csdn.net/weixin_73496371/article/details/135739915

这里我们就直接开始,我们先思考一个问题,阶乘调用了多少次函数?

老样子画图解释:

我们不断调用FAC从N次到N-1次再到N-2次...........直到0次

我们把它们相加起来就可以得到。

计算分析发现基本操作递归了N次,时间复杂度为O(N)。

我们再来看难度比较大的一道题:

// 计算斐波那契递归Fib的时间复杂度?
long long Fib(size_t N)
{
if(N < 3)
return 1;
return Fib(N-1) + Fib(N-2);
}

斐波那契我们用简单的图片来理解一下

理解起来有点像细胞分化的意思。

那么问题来了,一共有多少次调用呢?有个简易的方法来看一下

 我们观察最左边的数 2^0  2^1  2^2  2^3..........它们实际上是一个等比数列。

我们使用等比数列求和的方式求和.     这就用到了我们的高中知识。

通过计算分析发现基本操作递归了2^N次,时间复杂度为O(2^N)。

接下来为大家详解空间复杂度

空间复杂度

空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度 。
空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计算规则基本跟实践复杂度类似,也使用大O渐进表示法。
注意:函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。

实例1:

// 计算BubbleSort的空间复杂度?
void BubbleSort(int* a, int n)
{
assert(a);
for (size_t end = n; end > 0; --end)
{
int exchange = 0;
for (size_t i = 1; i < end; ++i)
{
if (a[i-1] > a[i])
{
Swap(&a[i-1], &a[i]);
exchange = 1;
}
}
if (exchange == 0)
break;
}
}

结论:    实例1使用了常数个额外空间,所以空间复杂度为 O(1)

解释:空间复杂度是我们一个算法在运行时额外(由于逻辑的需要)开辟的空间。

上述代码算法(排序过程)额外开辟的有 size_t end     size_t i    exchange它们开辟的空间都是常数,所以使用大O渐进法不难算出空间复杂度。 O(1)

 如果大家对这道题有疑问的话我们再来看一道题,相信你的问题不在是问题了。

实例2:

// 计算Fibonacci的空间复杂度?
// 返回斐波那契数列的前n项
long long* Fibonacci(size_t n)
{
if(n==0)
return NULL;
long long * fibArray = (long long *)malloc((n+1) * sizeof(long long));
fibArray[0] = 0;
fibArray[1] = 1;
for (int i = 2; i <= n ; ++i)
{
fibArray[i] = fibArray[i - 1] + fibArray [i - 2];
}
return fibArray;
}

我们观察在算法的运行中只动态开辟了(n+1)的空间。 ---------malloc((n+1)

那么我们使用大O渐进表示法:

动态开辟了N个空间,空间复杂度为 O(N)。

到这里我想大家对空间复杂度有了全新的理解了吧。

常见复杂度对比

一般算法常见的复杂度如下:

复杂度的oj练习 

消失的数字OJ链接:. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode-cn.com/problems/missing-number-lcci

感谢你的观看

后续更新更多数据结构的相关知识

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/765128.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

牛客NC101 压缩字符串(一)【简单 模拟 Java,Go,PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/c43a0d72d29941c1b65c857d8ac9047e 思路 直接模拟参考答案Java import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值…

备考ICA----Istio实验4---使用 Istio 进行金丝雀部署

备考ICA----Istio实验4—使用 Istio 进行金丝雀部署 上一个实验已经通过DestinationRule实现了部分金丝雀部署的功能,这个实验会更完整的模拟展示一个环境由v1慢慢过渡到v2版本的金丝雀发布. 1. 环境清理 kubectl delete gw/helloworld-gateway vs/helloworld dr/helloworld…

VS2017 remote debugger实现在线调试note

前言&#xff1a; 做为一个程序员&#xff0c; 必备的技能就是代码调试了&#xff0c;但是你们真的掌握了VS 的调试吗&#xff1f;有些时候由于线上环境和本地环境的差异&#xff0c; 导致本地可以运行&#xff0c; 但是线上确是存在异常的情况。也许可以通过Log 很快的定位到…

JavaEE--小Demo--数据库建立

目录 实验准备 本次所要新建的文件 实验步骤 step1-demo.sql 1.在resources文件夹下新建demo.sql文件 2.打开此目录&#xff0c;并运行命令提示符 3.打开数据库mysql -uroot -p 4.创建数据库create database demo; 5.使用数据库use demo; 6.导入数据source demo.sql;…

bochs模拟器中文文档

一、前言&#xff1a; 相信很多人都有使用模拟器的需求&#xff0c;因为并不是所有的场景都能用虚拟机代劳&#xff0c;如果你需要对程序精心的调试&#xff0c;实时查看内存与寄存器信息、研究指令集的工作原理&#xff0c;那么模拟器就是一种非常重要的工具。常见的模拟器有…

简介:KMeans聚类算法

在机器学习中&#xff0c;无监督学习一直是我们追求的方向&#xff0c;而其中的聚类算法更是发现隐藏数据结构与知识的有效手段。聚类是一种包括数据点分组的机器学习技术。给定一组数据点&#xff0c;我们可以用聚类算法将每个数据点分到特定的组中。 理论上&#xff0c;属于同…

海量数据处理项目-学以致用-商用短链平台需求文档拆分和总结

海量数据处理项目-学以致用-商用短链平台需求文档拆分和总结

提升Midjourney风格化的三个技巧

1. 引言 在前篇博文中&#xff0c;我们详细讲述了Midjourney的新功能风格参考的一些基础使用方法&#xff0c;事实上我们可以通过控制参数和提示权重进行更多的自定义操作&#xff0c;在本文中&#xff0c;我将向大家介绍我在网上搜集到的一些提升风格化效果的三个技巧。 闲话…

怎么卸载Mybatis?(仅需三步)

解决办法如下&#xff1a; 第一步&#xff1a;选择文件→设置 第二步&#xff1a;找到插件→输入Mybatis找到这个标志 第三步&#xff1a;把这个勾勾取消掉&#xff0c;点击确定&#xff0c;就可以轻松卸载了

hcip复习总结2(广域网与OSPF)

数据链路层面&#xff1a; 针对不同的物理链路定义不同的封装 局域网封装&#xff1a; Ethernet 2 &#xff08; TCP/IP &#xff09; &#xff0c; IEEE802.3 &#xff08; OSI &#xff09; 广域网封装&#xff1a; PPP HDLC FR ATM HDLC &#xff1a; 高级数据链路控制协…

备考ICA----Istio实验7---故障注入 Fault Injection 实验

备考ICA----Istio实验7—故障注入 Fault Injection 实验 Istio 的故障注入用于模拟应用程序中的故障现象&#xff0c;以测试应用程序的故障恢复能力。故障注入有两种: 1.delay延迟注入 2.abort中止注入 1. 环境准备 kubectl apply -f istio/samples/bookinfo/platform/kube/…

PTA题解 --- 阶梯电价(C语言)

今天是PTA题库解法讲解的第五天&#xff0c;今天我们要讲解A-B&#xff0c;题目如下&#xff1a; 解题思路&#xff1a; 要解决这个问题&#xff0c;我们可以编写一个C语言程序&#xff0c;首先判断输入的月用电量是否有效&#xff08;即大于等于0&#xff09;。如果有效&…

面试笔记——MySQL(主从同步原理、分库分表)

主从同步原理 主从同步结构&#xff1a;主库负责写数据&#xff0c;从库负责读数据&#xff0c;如图—— MySQL主从复制的核心就是二进制日志&#xff08;BINLOG&#xff09;&#xff0c;它记录了所有的 DDL&#xff08;数据定义语言&#xff09;语句和 DML&#xff08;数据操…

Linux centos7安装nginx-1.24.0并且实现自启动

1.安装之前的操作 ps -ef|grep nginx 查看是否有运行 如果有就杀掉 kill -9 pid find / -name nginx 查看nginx文件 rm -rf file /usr/local/nginx* 通通删掉删掉 yum remove nginx 限载一下服务 1.2.下载安装包 地址 nginx: download 2.减压文件 tar…

二叉树的层次遍历经典问题-算法通关村

二叉树的层次遍历经典问题-算法通关村 1 层次遍历简介 广度优先在面试里出现的频率非常高&#xff0c;整体属于简单题。广度优先又叫层次遍历&#xff0c;基本过程如下&#xff1a; 层次遍历就是从根节点开始&#xff0c;先访问根节点下面一层全部元素&#xff0c;再访问之后…

stable diffusion 提示词进阶语法-年龄身材肤色-学习小结

stable diffusion 提示词进阶语法-年龄&身材&肤色 前言年龄提示词青年&#xff08;18-25岁&#xff09;幼年、少年&#xff08;1-18&#xff09;中年&#xff08;35-60岁&#xff09;老年&#xff08;65-80岁 老爷爷 老奶奶&#xff09; 身材提示词肤色关键词(人物基础…

Ubuntu 22.04安装Python3.10.13

Ubuntu最好设置为英文&#xff0c;我之前用中文在make的test的时候&#xff0c;总是会有fail。 查了下有人怀疑是language的问题&#xff0c;保险起见都用英文&#xff0c;个人实践也证明改为英文就不报错了。 issue 44031: test_embed and test_tabnanny fails if the curre…

删除了几个月的照片能找回么 怎么找回半年前删除的照片 数据恢复软件推荐

照片定格了风景&#xff0c;保存了记忆&#xff0c;是我们对过往的一种留念。在数字化的今天&#xff0c;我们越来越习惯把照片存放在电脑里面&#xff0c;随着占用的空间越来越大&#xff0c;我们也会经常处理不用的照片。当然&#xff0c;难免有时候也会误删有用的照片。本篇…

STM32 AD单通道函数设计

单片机学习&#xff01; 目录 文章目录 前言 一、ADC配置步骤 二、详细步骤 2.1 开启RCC时钟 2.2 配置GPIO 2.3 配置多路开关 2.4 配置ADC转换器 2.5 开启ADC电源 2.6 ADC进行校准 2.6.1 复位校准 2.6.2 等待复位校准完成 2.6.3 开始校准 2.6.4 等待校准完成 三、启动AD转换函数…

STM32不使用中断实现定时器微秒级精确延时

我们在写代码的时候避免不了要使用延时函数&#xff0c;很多延时函数都是使用中断或者tick来实现的&#xff0c;tick的方式最大到毫秒ms级别&#xff0c;通过中断方式的通用定时器来实现&#xff0c;如果实现1us的延时那么每1us就来一次中断&#xff0c;很影响cpu的效率。 本文…