成为编程大佬!!——数据结构与算法(1)——算法复杂度!!

news2024/10/2 20:35:16

前言:解决同一个程序问题可以通过多个算法解决,那么要怎样判断一个算法的优劣呢?🤔

算法复杂度

算法复杂度是对某个程序运行时的时空效率粗略估算,常用来判断一个算法的好坏。

我们通过两个维度来看算法复杂度——时间复杂度 和 空间复杂度

时间复杂度

随着计算机科学技术的发展,计算机的内存从原来的256MB、512MB直到现在的16G甚至32G,存储空间的限制逐渐减小。因此,现在对于程序算法复杂度,更多地关注到时间上面去。

不难知道,假设每条语句的执行时间相同,则有:

程序运行所需要的总时间 = 每条语句的执行时间 x 执行语句的次数——①

这条公式里,执行次数是可以确定的,但是执行时间缺难以确定

int begin = clock();//clock()函数返回程序运行到当前位置已花费的时间。
int count = 0;
for(int i = 0; i < 100000000; ++i)
{
    count++;
}
int end = clock();
printf("%d",begin - end);//打印循环完毕后总共消耗的时间

PS:clock()函数包含在头文件time.h中,返回值的时间单位是毫秒。

我们可以试着在本地多次运行这段代码,然后就可以发现,并不是每一次的运行时间都是相同的,但是相差并不大。

而对于复杂度来说,我们只需要进行粗略的估算即可,因此,我们省略公式①中对执行时间的计算,只关注可以准确计算得出的执行次数。

T(N)函数式

时间复杂度的T(N) 函数式用来表示程序的执行语句次数。

​int time = 0;//------------1
scanf("%d", &time);//-----------1​
int count = 0;//---------1
for(int i = 0; i < time; ++i)
{
    for(int j = 0; j < time; ++j)
    {
        count++;//-------------N*N
        printf("%d ", count);//---------N*N
    }
}
for(int i = 0; i < time; ++i)
{
    count--;//------------N
}
printf("%d",count);//--------1
count = 0;//-----------1

​

​

​

如上代码,我们来用T(N)表达式来表示执行语句次数,可得:                  T(N)=1+1+1+n*n+n*n+n+1+1 = 2N^{2}+N+5

这段代码,对执行次数有影响的是time,所以把 time 作为T(N)函数式的变量,用大写字母N来替换。最终  2N^{2}+N+5 就表示这段代码的执行语句次数。

大O渐进表示法

T(N)函数式还不是我们需要的最终结果,复杂度的最终结果,是一个数量级结果。那我们就要根据T(N)函数式,并运用大O渐进表示法来求得数量级结果。(下面用上文求得的T(N)函数式作例子)

基本规则:

①先求得T(N)函数式。(若对执行语句次数有影响的变量不止一个,函数式就为T(N,M,……)。)已求得T(N)= 2N^{2}+N+5 。

②取T(N)中最高阶项。取得2N^{2}

③最高阶项舍去系数(系数取1)。得N^{2}

④放入O()的括号中。得O(N^{2})。

O(N^{2})就是上述代码的时间复杂度结果。根据O(N^{2})我们可知,上述代码的时间复杂度是平方级的。

其他规则:

其他规则也务必得遵守其他规则才ok喔。

⑤若最高阶项为常数,则均表示为O(1),表示数量级为常数级。

⑥对于被多个变量的影响执行次数的程序来说:

i.T(N)函数式就有多个变量,我们一般依次用N,M,L,……来替换表示,最终得到一个多元函数式。如T(N,M) = N + M。

ii.不同的变量,各自遵守②③进行取舍。若有如取舍后的结果为 N^{2}+N*M就要分情况讨论

N远大于M,则把M看作1;

M远大于N,就把N看作1;

如果N、M相差不大,可以把 N看成M 或者 M看成N

再进一步取舍,得到最终答案。

当然,不分情况讨论也是正确的大O表示法结果,但是我们更需要的是一个数量级结果,所以,我们最好如上进行进一步讨论

对数级复杂度,即O(\lg N)、O(\log_{2}N)等等,可以写做O(\log N)省去底数

会出现对数级复杂度的例子:

int k = 2;//-------------1
int n = 0;//------------1
scanf("%d", &n);//----------1
while(k < n)
{
    k *= 2;//------------2^k < n时循环,结束时2^k > n
}
printf("%d", k);

可得程序结束时,有2^{k+1} >  2^{k} > n,可求得循环次数N = \log_{2}n,即k乘了N次2。T(N)=\log_{2}n,时间复杂度为O(\log N),或者O(\log_{2}N)皆可(因为底数对于对数得最终结果影响很小,所以一般都写成第一种情况)

递归情况

如下代码,求n的阶乘:

int fac(int n)
{
    if(n == 0)
    {
        return 1;
    }
    return fac(n - 1) * n;
}

可知求阶乘要进行n层递归。同时,肉眼可见,每次递归的时间复杂度为O(1),因此,完成n层递归的时间复杂度为 N * O(1)= O(N)。(也就是直接在数量级层面做乘法即可

以上规则已足够应对对大多数程序的算法判断了。

空间复杂度

即使存储空间现在已经不是重头问题了,但是存储空间也不能随意浪费。空间复杂度仍然是算法好坏的评判标准之一。

T(N)函数式

空间复杂度的T(N)函数式用来表示 程序运行时 创建的 空间个数

运行时创建的空间——编译完成之后,创建的所有空间。包括全局变量,局部变量,函数栈帧……

空间个数——不考虑空间的大小,只考虑开辟空间的个数

注意

i.数组的空间个数为数组长度。

ii.动态申请的空间,如malloc(sizeof(int)*n),这个语句的T(N)=N。

​
int func(int** arr, int n)
{
    *arr = (int*)malloc(sizeof(int) * n);//-------------n
    if(!*arr)
    {
        perror("malloc");
        return 0;
    }
    return 1;   
}

int main()
{
    int* arr = NULL;//----------------1
    scanf("%d", &n);
    func(&arr, n);//------------1——函数栈帧(里面包含了形参的开辟空间)
    return 0;
}

​

T(N)=1+1+n=N+2,其中两个1,分别是指针arr的空间,和func函数栈帧的空间;n为func中动态申请的空间

然后同时间复杂度一样,通过大O渐进表示法来求得最终空间复杂度结果。

最终上述代码的空间复杂度是O(N)。

结语

看完这篇博客,相信你已经对算法复杂度有了深刻认识了。有什么疑问和困惑欢迎来评论区留言!!🤩我一定尽力及时解答!!制作不易,求关注!!求点赞!!之后还会有更多有用的干货博客会发出哦!!欢迎做客我的主页!!❤❤Elnaij-CSDN博客❤❤

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

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

相关文章

记录docker部署好golang web项目后浏览器访问不到的问题

部署好项目&#xff0c;docker ps -a查看没有任何问题 端口映射成功&#xff0c;但是浏览器就是访问不到&#xff0c;排查后发现犯了个错&#xff0c;注意&#xff0c;项目配置文件中的端口&#xff1a; 其实也就是你项目中监听的端口&#xff1a; 必须和容器端口一致&#x…

Linux——多线程(四)

前言 这是之前基于阻塞队列的生产消费模型中Enqueue的代码 void Enqueue(const T &in) // 生产者用的接口{pthread_mutex_lock(&_mutex);while(IsFull())//判断队列是否已经满了{pthread_cond_wait(&_product_cond, &_mutex); //满的时候就在此情况下等待// 1.…

看影视学英语(假如第一季第一集)

in the hour也代表一小时吗&#xff1f;等同于in an hour&#xff1f;

Effective C++笔记之二十一:One Definition Rule(ODR)

ODR细节有点复杂&#xff0c;跨越各种情况。基本内容如下&#xff1a; ●普通&#xff08;非模板&#xff09;的noninline函数和成员函数、noninline全局变量、静态数据成员在整个程序中都应当只定义一次。 ●class类型&#xff08;包括structs和unions&#xff09;、模板&…

独立开发者系列(23)——Linux掌握小结

只要开发系统&#xff0c;就绕不开使用Linux服务器 &#xff0c;而Linux除了使用BT面板进行初级管理&#xff0c;很多稍微高级点的管理&#xff0c;还是需要命令行进行的。这里总结在不需要精通的情况下&#xff0c;掌握常见命令和环境的相关配置。 &#xff08;1&#xff09…

Linux学习之网络配置问题

Linux学习——那些我们网络配置遇到过的问题&#xff1f;ping不通百度&#xff1f;XShell连接不上&#xff1f;&#xff08;超详细&#xff09; &#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感…

HTML 标签简写及全称:表格内容将通过JavaScript动态生成

<!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>HTML 标签简写及全称</title><style>…

振弦采集仪在大型工程安全监测中的作用与意义

振弦采集仪在大型工程安全监测中的作用与意义 河北稳控科技振弦采集仪是一种用于测量振动频率的仪器&#xff0c;常用于大型工程的安全监测中。它通过采集振弦的振动信号&#xff0c;可以对工程结构的振动特性进行实时监测和分析。振弦采集仪在大型工程安全监测中具有重要的作…

【目标跟踪】CoTracker 环境配置

配置 CoTracker 环境 首先下载 conda&#xff0c;然后安装虚拟环境。 1.创建环境&#xff1a;如果环境不存在&#xff0c;你需要创建一个新的 conda 环境。可以使用以下命令创建名为 cotracker 的环境&#xff1a; conda create -n cotracker python3.x 其中 3.x 是你想要安…

C语言程序题(一)

一.三个整数从大到小输出 首先做这个题目需要知道理清排序的思路&#xff0c;通过比较三个整数的值&#xff0c;使之从大到小输出。解这道题有很多方法我就总结了两种方法&#xff1a;一是通过中间变量比较和交换&#xff0c;二是可以用冒泡排序法&#xff08;虽然三个数字排序…

【UE5.3】笔记9

1、如何将BSP笔刷转换为静态网格体&#xff1f; 在笔刷的细节的高级里面找到创建静态网格体&#xff1b; 2、如何将自己创建的一个由多个网格体或其他组件组合成的道具转换为个整体即蓝图类&#xff1f;---即把多个Actor转换成蓝图类 选中所要整合的对象&#xff0c;要全选中…

js原型和类---prototype,__proto__,new,class

原型和原型链 在js中&#xff0c;所有的变量都有原型&#xff0c;原型也可以有原型&#xff0c;原型最终都指向Object 什么是原型 在js中&#xff0c;一个变量被创建出来&#xff0c;它就会被绑定一个原型&#xff1b;比如说&#xff0c;任何一个变量都可以使用console.log打…

数据结构 Java DS——链表部分经典题目 (1)

前言 笔者计划在暑假啃完JavaDS,Mysql的内容当然也会继续更 这次给读者们分享的是链表的几个比较典型的题目,关于如何手搓一个链表,笔者还在筹划中, 毕竟链表的种类也有那么多,但是在下面的题目中,只有单向链表 题目一 : 反转链表 206. 反转链表 - 力扣&#xff08;LeetCode…

文献笔记|综述|When Large Language Model Meets Optimization

When Large Language Model Meets Optimization 题目&#xff1a;当大型语言模型遇到优化时 作者&#xff1a;Sen Huang , Kaixiang Yang , Sheng Qi and Rui Wang 来源&#xff1a;arXiv 单位&#xff1a;华南理工大学 文章目录 When Large Language Model Meets Optimization…

java:字符缓冲流特有功能

BufferedWriter&#xff1a; void newLine&#xff08;&#xff09;&#xff1a;写一行行分隔符&#xff0c;行分隔符字符串由系统属性定义 BufferedReader&#xff1a; public String readLine&#xff08;&#xff09;&#xff1a;读一行文字&#xff0c;结果包含行的内容的字…

Mosh|初学者 SQL 教程

sql文件链接&#xff1a;链接: https://pan.baidu.com/s/1okjsgssdxMkfKf8FEos7DA?pwdf9a9 提取码: f9a9 在mysql workbench 导入 create_databases.sql 文件&#xff0c;下面是运行成功的界面 快捷方式&#xff1a;全部运行可以同时按下controlcommandenter &#xff0c;或者…

rsync远程同步--累了,明天继续再写~。

rsync官网链接 rsync(Remote Sync,远程同步)开源快速备份工具&#xff0c;是一个用于本地和远程文件同步的Unix-like命令行程序。它使用“快速数据传输算法”&#xff0c;只发送源和目标之间的差异&#xff0c;因此数据传输非常高效。 可以在不同主机之间镜像同步整 个目录树…

基于网络编码的 tcp 变种-tcp/nc

tcp/nc 是指 “tcp with network coding”&#xff0c;是一种结合了网络编码技术的 tcp 变种&#xff0c;网上资源很少&#xff0c;我也不准备多介绍&#xff0c;只介绍它的核心。 传统 tcp 在演进过程中一直搞不定效率问题&#xff0c;网络带宽在增长&#xff0c;cpu 却没有变…

Python学习中使用循环(for, while)

在Python编程语言中&#xff0c;循环是一个非常重要的概念&#xff0c;可以帮助我们在代码中重复执行某些操作。Python支持两种主要的循环结构&#xff1a;for 循环和 while 循环。 1. for 循环 for 循环用于遍历一个序列&#xff08;如列表、元组、字符串&#xff09;或其他…

自动化数据集成的BI工具,为你提供决策洞察力

传统的商业智能&#xff08;BI&#xff09;报表系统采用的是“业务提报表需求&#xff0c;IT进行开发”的模式。决策管理者和业务人员提出用报表等来展示经营管理数据的需求&#xff1b;接着IT响应需求&#xff0c;进行需求沟通、数据处理加工、报表开发等主体工作&#xff1b;…