当前位置: 首页 > news >正文

时间复杂度(超详解+例题)

全文目录

  • 引言
    • 如何衡量一个算法的好坏
  • 时间复杂度
    • 时间复杂度的定义
    • 时间复杂度的大O表示法
  • 实例
    • test1
    • test2
    • test3
    • test4
    • test5
  • 总结

引言

如何衡量一个算法的好坏

我们在写算法的时候,对于实现同样的作用的不同算法,我们如何判断这个算法的好坏呢?

我们很容易的想到可以通过这个算法计算某用例的时间与所额外占用的空间来判断。
但是对于不同的计算机而言,数据读取与处理的速度与方式是可以有很大的差别的。所以单纯的根据算法某次运行的时间与空间来判断算法的效率高低是没有说服力的。

所以,我们使用时间复杂度与空间复杂度这两个标准来衡量算法的效率的高低。
在本篇文章中将介绍时间复杂度:

时间复杂度

时间复杂度的定义

在计算机科学中,时间复杂度是一个函数,它定量的描述了一个算法运行的时间。

前面提到,要实际的测出算法的运行时间是很麻烦的,有很多的不确定变量。而算法运行的时间往往与其中语句的执行次数成正比,所以算法中基本语句的执行次数为算法的时间复杂度。

时间复杂度的函数就是基本语句数量与相关变量之间的数学关系式。

例如:

int fun(int n)
{int i = 0;int j = 0;int count = 0;for (i = 0; i < n; i++){for (j = 0; j < n; j++){count++;}}for (i = 0; i < 2 * n; i++){count++;}int m = 10;while (m--){count++;}return count;
}

在这段代码中:

基本语句的数量与变量n与变量m有关,而m的值是恒定的。
所以我们可以得到这个函数的时间复杂度的数学表达式为 n^2+2*n+10。

虽然对于上面的代码而言,找到精确的数学表达式来表示时间复杂度是很容易的,但是对于一些比较复杂的算法而言,想要找到精确的函数是很困难的。所以我们使用大O表示法来表示时间复杂度的大概值。

时间复杂度的大O表示法

大O符号是用于描述函数渐进行为的数学符号。

我们在使用大O表示法表示时间复杂度时,去掉对结果影响不大的项即可。
大O表示法的转换规则如下:

1、用常数1表示算法中的所有加法常数;
2、在修改后的数学表达式中只保留最高项;
3、如果最高项存在且不是1,则去掉该最高项的系数。
得到的结果就是大O阶。

对于上面的fun函数:
我们已经得到了该数学表达式:n^2+2*n+10。
首先将常数10改为1;再将最高项保留,即n^2;这一项的系数为1。
所以大O阶就为 O(n^2)

另外,某些算法在运行时对于不同的用例可能会有不同的情况。这时,我们采取最慢的情况来计算时间复杂度。

实例

在实际用大O阶表示时间复杂度的时候,我们其实并不用通过精确的数学表达式来推出,只需要将该算法基本语句的量级表示出来即可。例如对数级(log n)、正比例级(n)、次方级(n^2)、指数级(2^n)等。这些量级都是可以用函数图像表示出来的:
在这里插入图片描述

例如上面的fun函数的量级就是n^2级的。

而确认量级的最佳途径往往是画图,接下来将通过几个栗子来说明:

test1

void test1(int N)
{int count = 0;for (int k = 0; k < 100; ++k){++count;}printf("%d\n", count);
}

在这段代码中:
显然,算法的基本操作的数量与k相关。

k的值从0开始随着算法的执行递增1,到100终止。所以我们可以画出它大概的图像:
在这里插入图片描述
根据大O阶表示法,这个算法的时间复杂度就是O(1)。

test2

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;}
}

这个算法就是经典的冒泡排序算法。
对于冒泡排序算法,最好的情况是输入的数据已经是升序排列的,这种情况下只需要执行n次基本语句即可:
在这里插入图片描述
最坏的情况是完全降序的排列,此时就需要完全执行每一个基本语句,需要执行n^n次:
在这里插入图片描述

test3

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;elsereturn mid;}return -1;
}

这段代码就是经典的二分查找算法:

对于二分查找,是从n开始每次范围减少一半,知道剩余1个元素。
所以1乘以2的查找次数次方就是n,即需要执行log n次。我们就可以画出关系图:
在这里插入图片描述
需要注意的是,由于书写较麻烦,对于log以2为底n的对数,所以可以用log n表示。

test4

long long Fac(size_t N)
{if (0 == N)return 1;return Fac(N - 1) * N;
}

这是一个函数递归的算法:

将N-1的值再传给函数本身,直到N为0时终止递归。
很明显,该算法每次递归N递减1,所以执行N次基本语句:

在这里插入图片描述

test5

long long Fib(size_t N)
{if (N < 3)return 1;return Fib(N - 1) + Fib(N - 2);
}

这是一个递归实现斐波那契数列的算法:

对于该算法,每次递归都会引起两次递归,即两次基本语句(N-1与N-2)。直到参数<3终止。
我们可以先画出这个算法的程序图:
在这里插入图片描述
不难发现,基本语句的量级是指数增长的,所以该算法的时间复杂度为O(2^n):
在这里插入图片描述

总结

到此,关于时间复杂度的知识就介绍完了。
在下一篇文章中将详细介绍空间复杂度的相关知识,希望持续关注哦

如果大家认为我对某一部分没有介绍清楚或者某一部分出了问题,欢迎大家在评论区提出

如果本文对你有帮助,希望一键三连哦

希望与大家共同进步哦

相关文章:

时间复杂度(超详解+例题)

全文目录引言如何衡量一个算法的好坏时间复杂度时间复杂度的定义时间复杂度的大O表示法实例test1test2test3test4test5总结引言 如何衡量一个算法的好坏 我们在写算法的时候&#xff0c;对于实现同样的作用的不同算法&#xff0c;我们如何判断这个算法的好坏呢&#xff1f; …...

【Java面试总结】Maven篇

【Java面试总结】Maven篇1.Maven坐标是啥2.Maven常见的依赖范围有哪些?3.多模块如何聚合4.对于一个多模块项目&#xff0c;如果管理项目依赖的版本5.maven怎么解决版本冲突6.Maven常用命令有哪些&#xff1f;1.Maven坐标是啥 一般maven使用groupID&#xff0c;artifactId&…...

【每日一题Day123】LC1792最大平均通过率 | 堆

最大平均通过率【LC1792】 一所学校里有一些班级&#xff0c;每个班级里有一些学生&#xff0c;现在每个班都会进行一场期末考试。给你一个二维数组 classes &#xff0c;其中 classes[i] [passi, totali] &#xff0c;表示你提前知道了第 i 个班级总共有 totali 个学生&#…...

[安装之5] Mac pro更换大内存固态硬盘实践教程

近由于mac电脑内存吃紧&#xff0c;安装大的软件&#xff0c;是不是要提示一下内存不够&#xff0c;内心非常的不爽。作为一款A1502版的mac&#xff0c;128G固态硬盘通常被称为“乞丐版”。提前做好准备工作后&#xff0c;我周末花了一天的时间搞定这件事&#xff0c;为了能够帮…...

04 Python变量的声明与使用

基本上,在所有的计算机编程语言中,都会用到变量,变量将数据存储在计算机内存中。 变量是指存储数据的内存地址,通过变量名,我们可以找到这个变量名对应的内容。 命名变量时不允许使用数字、特殊字符、连字符开头。 变量可以有一个短名称(如 x、y、z),但强烈建议使用更具…...

LeetCode 2418. 按身高排序

给你一个字符串数组 names &#xff0c;和一个由 互不相同 的正整数组成的数组 heights 。两个数组的长度均为 n 。 对于每个下标 i&#xff0c;names[i] 和 heights[i] 表示第 i 个人的名字和身高。 请按身高 降序 顺序返回对应的名字数组 names 。 示例 1&#xff1a; 输…...

一文了解Hotspot虚拟机下JAVA对象从创建到回收的生命周期

Java虚拟机是Java的核心和基础&#xff0c;他是Java编译器和操作系统平台之间处理器&#xff0c;能实现跨平台运行Java程序。本文主要讲解的是虚拟机如何管理对象&#xff0c;即Java对象在JVM虚拟机中被创建到回收的流程 Java对象从创建到回收的生命周期对象创建流程1.类加载检…...

【Java基础】Java对象创建的几种方式

先上关键内容&#xff0c;所用到的代码请参考文末示例代码。一、使用new关键字创建对象这是一种最常用的创建对象的方式。Student student1 new Student();二、使用Class的newInstance()方法创建对象需要有一个无参构造方法&#xff0c;这个newInstance()方法调用无参的构造函…...

社保缴费满15年就可以不缴了?6个很多人最关心的问题权威解答来了

一、社保缴费满15年就可以不缴了&#xff1f; 上海市政府新闻办公室2022年在微信号发文表示&#xff0c;社会保险是由国家通过立法强制建立的社会保障制度&#xff0c;用人单位和劳动者都必须依法参加社会保险。即使职工与用人单位商议签订了不参加社保的所谓“协议”&#xf…...

关于HDFS

目录 一、HDFS概述 二、HDFS架构与工作机制 三、HDFS的Shell操作 四、Hdfs的API操作 一、HDFS概述 HDFS&#xff1a;Hadoop Distributed File System&#xff1b;一种分布式文件管理系统&#xff0c;通过目录树定位文件。使用场景&#xff1a;一次写入&#xff0c;多次读出…...

C++入门:类 对象

C 在 C 语言的基础上增加了面向对象编程&#xff0c;C 支持面向对象程序设计。类是 C 的核心特性&#xff0c;通常被称为用户定义的类型。类用于指定对象的形式&#xff0c;它包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员。函数在一个类中被称为类的成…...

Python生日系统

#免费源码见文末公众号# 录入生日 def write():keyvar1.get()valuevar2.get()with open(d:\\生日系统.pickle,rb) as file:dictspickle.load(file)dicts[key]valuewith open(d:\\生日系统.pickle,wb) as file:pickle.dump(dicts,file)file.close() 查询生日 def read():namev…...

< CSDN周赛解析:第 28 期 >

CSDN周赛解析&#xff1a;第 27 期&#x1f449; 第一题&#xff1a; 小Q的鲜榨柠檬汁> 题目解析> 解决方案&#x1f449; 第二题&#xff1a; 三而竭> 解析> 解决方案> 拓展知识&#x1f449; 第三题&#xff1a; 隧道逃生> 解析> 解决方案&#x1f449;…...

【题外话】如何拯救小米11Pro这款工业垃圾

1 背景媳妇用小米11Pro手机&#xff0c;某日不慎摔落&#xff0c;幸好屏幕未碎&#xff0c;然而WiFi却怎样都无法打开&#xff0c;初以为是系统死机&#xff0c;几天依旧故障无法使用。现在的手机没有WiFi功能&#xff0c;就无法刷抖音、看视频&#xff0c;就是鸡肋了。后抽空去…...

Python中有哪些常用操作?这20个你都会吗

Python 是一个解释型语言&#xff0c;可读性与易用性让它越来越热门。 正如 Python 之禅中所述&#xff1a; 优美胜于丑陋&#xff0c;明了胜于晦涩。 在你的日常编码中&#xff0c;以下技巧可以给你带来意想不到的收获。 1、字符串反转 下面的代码片段&#xff0c;使用 P…...

【LeetCode】剑指 Offer(4)

目录 写在前面&#xff1a; 题目&#xff1a;剑指 Offer 10- I. 斐波那契数列 - 力扣&#xff08;Leetcode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 题目&#xff1a;剑指 Offer 10- II. …...

庄懂的TA笔记(十二)<>

庄懂的TA笔记&#xff08;十二&#xff09;&#xff1c;&#xff1e;一、作业展示&#xff0c;答疑&#xff1a;1、作业&#xff1a;2、答疑&#xff1a;二、作业示范&#xff0c;分析&#xff1a;1、文档分析&#xff1a;2、资源分析&#xff1a;3、资源优化&#xff1a;4、光…...

学分绩点(2023寒假每日一题 5)

北京大学对本科生的成绩施行平均学分绩点制&#xff08;GPA&#xff09;。 既将学生的实际考分根据不同的学科的不同学分按一定的公式进行计算。 公式如下&#xff1a; 实际成绩 绩点 90——100 4.0 85——89 3.7 82——84 3.3 78——81 3.0 75…...

Framework学习之旅:Zygote进程

概述 在Android系统中&#xff0c;DVM(Dalvik 虚拟机和ART、应用程序进程以及运行系统的关键服务SystemServer进程都是由Zygote进程来创建的。通过fork&#xff08;复制进程&#xff09;的形式来创建应用程进程和SystemServer进程&#xff0c;由于Zygote进程在启动时会创建DVM…...

HTTP基础知识

关键字&#xff1a;一问一答用于和服务器交互什么是HTTPHTTP是个应用层协议&#xff0c;是HTTP客户端和HTTP服务器之间的交互数据格式。所以这里有个实例&#xff1a;在浏览网页的时候&#xff0c;浏览器会向服务器发送一个HTTP请求&#xff0c;告诉服务器我想访问什么..然后服…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...