【数据结构】算法复杂度

news2025/1/14 1:21:10

文章目录

  • 引入
    • 算法复杂度
  • 一.时间复杂度
    • 定义
    • 大O渐进表示法
    • 经典例题
      • 常量
      • 字符串
      • 二分查找
      • 冒泡排序
      • 递归
        • 1.阶乘
        • 2.斐波切纳数列
  • 二.空间复杂度
    • 定义
    • 经典例题
      • 冒泡排序
      • 递归
        • 1.阶乘
        • 2.斐波切纳数列

引入

为什么要有算法复杂度?
当我们正在解决一个问题的时候,想出了多种思路,我们需要找出符合题目的解法(有的题会要求算法复杂度),那学习算法复杂度正是需要我们解题的关键。

算法复杂度

算法在编写成可执行程序后,运行时需要耗费时间资源空间(内存)资源 。
因此衡量一个算法的好坏,一般是从
时间和空间
两个维度来衡量的,即时间复杂度和空间复杂度。
说明:
1.时间复杂度主要衡量一个算法的运行快慢
2.空间复杂度主要衡量一个算法运行所需要的额外空间
补充:
1.在计算机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。
2.摩尔定律

一.时间复杂度

定义

在计算机科学中,时间复杂性,又称时间复杂度,算法的时间复杂度是一个函数,它定性描述该算法的运行时间。这是一个代表算法输入值的字符串的长度的函数。

void Func1(int N)
{
	int count = 0;
	for (int i = 0; i < N ; ++ i)
	{
		for (int j = 0; j < N ; ++ j)
		{
			++count;
		}
	}
	for (int k = 0; k < 2 * N ; ++ k)
	{
		++count;
	}
	int M = 10;
	while (M--)
	{
		++count;
	}

我们看一下循环的执行次数——与N和M有关
列出精确的函数的表示式 :   F(N)=N*N+2N+10
这是我们平常见到的时间复杂度吗?
答案:NO

大O渐进表示法

承接上文

1.我们需要无比精确的表示函数里面循环的执行次数吗?不需要
2.这样做在实际中是不是比较麻烦呢?是
3.那有什么办更为简便吗?有

这就引出了此法。
我觉得再学过高等数学的极限思想会更容易理解,那就是看影响比较大的部分,当变量很大的时候,看影响更大的一部分,即为当变量趋于无穷时,函数表达式等价的式子
再看上面的代码:
列出精确的函数的表示式:F(N)=NN+2N+10
当N趋于无穷(很大)的时候对函数表达式影响最大的是N
N的式子。
那么上面代码的时间复杂度为:O(N^2)

注意:
这里变量通常为N的表达式,但是有的时候也会出现变量X,M,Y 等的表达式,甚至是M*N之类的。

常见的算法复杂度:
在这里插入图片描述

经典例题

常量

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

这里循环了100次。
对于常量:用O(1)表示

字符串

const char * strchr ( const char * str, int character )
{
   while(*str)
   {
      if(*str==character)
      {
         return str;
      }
      else
      {
          str++;
      }
   }
  return NULL;
}

一般会从三个角度进行思考

1.最好的情况
例如:假设要在字符串“abcdefg”查找 ‘a’只查找了1次
2.平均的情况
例如:假设要在字符串“abcdefg”查找 ‘d’查找了4次
3.最坏的情况
例如:假设要在字符串“abcdefg”查找 'h’查找了7次

那我们假设字符串的长度为N
最好的情况:1
平均的情况:(1+N)/2
最好的情况:N
我们要衡量的尺度一般是从最坏的情况进行考虑:N
那么这里的时间复杂度为:O(N)

二分查找

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);//这与(begin+end)/2的效果差不多
			if (a[mid] < x)
				begin = mid+1;
			else if (a[mid] > x)
				end = mid-1;
			else
				return mid;
			}
	return -1;
}

图解:
在这里插入图片描述

冒泡排序

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.阶乘

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

图解:
在这里插入图片描述

2.斐波切纳数列

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

图解:
在这里插入图片描述

注意:
这里函数的运行的顺序,为接下来的空间复杂度做铺垫(这里看不懂没关系)
图解:
在这里插入图片描述

二.空间复杂度

定义

空间复杂度(Space Complexity)是对一个算法在运行过程临时占用存储空间大小的量度,记做S(n)=O(f(n))。

补充:这里也采用大O渐进法

注意:
函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。

经典例题

冒泡排序

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.阶乘

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

图解:
在这里插入图片描述

2.斐波切纳数列

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

图解:

注意:
这里函数的运行的顺序

在这里插入图片描述

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

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

相关文章

【计算机基础】操作系统

前言&#xff1a;本文适合用于基础了解和背诵&#xff0c;尽可能采用流畅且简短的语言回答操作系统相关问题并且辅以图片帮助记忆&#xff0c;不适合用作详细了解与深入学习 。 总述 操作系统部分主要分为以下几个重点 —— 操作系统基础 、 进程和线程、操作系统的内存管理、…

JAVA基础知识07常用API

目录 1. 常用API 1.1 简介 1.2 String类 1.2.1 字符串在开发中的应用场景 1.2.2 String 类的特点 1.2.3 String 类的常见构造方法 1.2.4 String 类的常见面试题 1.2.5 面试题题解 1.2.6 String 类用于比较的方法 1.2.7 String 字符串的遍历 1.2.8 String 字符串的截取…

QByteArray字节流和二进制与字符的关系以及tohex() toLatin1

QByteArray 存储的是字节&#xff0c;二进制形式&#xff0c;即ascii码的二进制编码。输出的时候&#xff0c;会输出二进制对应的字符 即一个映射: 二进制到ascii码的映射而.tohex()会将二进制转化为16进制字符&#xff0c;这里的16进制字符又是作为值域了&#xff0c;实际存…

JavaEE-文件和IO(二)

目录2.2 文件内容相关的操作三、文件操作案例3.1 案例一3.2 案例二3.3 案例三2.2 文件内容相关的操作 打开文件读文件写文件关闭文件 针对文件内容的读写&#xff0c;java标准库提供了一组类~ 首先按照文件的内容&#xff0c;分为两个系列 字节流对象&#xff0c;针对二进制…

手把手教你写web全栈入门项目—React+Koa+MongoDB(3w字教程,真的很详细,有代码)

手把手教你写web全栈入门项目—ReactKoaMongoDB 文章目录手把手教你写web全栈入门项目—ReactKoaMongoDB前言一、推荐基础二、所需环境三、软件四、项目源码五、文章结构六、遇到问题怎么办前端一、页面登录页首页二、目录结构三、技术选择四、开始项目1、页面组件1.1 目录1.2 …

JavaScript 所见所得文本编辑器 Froala Editor 4.0.17Crack

Froala Editor v4.0.17 清除格式工具现在可以从粘贴的内容中删除内联样式。 2023 年 1 月 24 日 - 9:07新版本 特征 清除格式工具现在可以从粘贴的内容中删除内联样式。 改进的“删除时保留格式”功能可保留已删除文本的格式并将其应用于替换文本。 选择图像时&#xff0c;用于…

day20|77. 组合。回溯的开始

回溯思路 void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择&#xff1a;本层集合中元素&#xff08;树中节点孩子的数量就是集合的大小&#xff09;) {处理节点;backtracking(路径&#xff0c;选择列表); // 递归回溯&#xff0c;撤销处理结果} } 77. 组合…

91.使用注意力机制的seq2seq以及代码实现

1. 动机 2. 加入注意力 key和value是一样的 假设英语句子长为3的话&#xff0c;就会有3个key-value pair&#xff0c;key和vlaue是一个东西&#xff0c;每一个key-value pair对应第i个词的RNN的输出。之前的seq2seq只使用了最后的key-value&#xff0c;现在则是把所有的key-val…

JavaWeb语法八:网络原理初识

目录 1.局域网与广域网 1.1&#xff1a;局域网 1.2&#xff1a;广域网 2&#xff1a;网络基础知识 3.协议分层 3.1&#xff1a;分层的好处 3.2&#xff1a;TCP/IP五层&#xff08;或四层&#xff09;模式 4&#xff1a;封装和分用 4.1&#xff1a;封装 4.2&#xff1…

MyBatisPlus入门简介

目录 1. 入门案例 问题导入 1.1 SpringBoot整合MyBatisPlus入门程序 2. MyBatisPlus概述 问题导入 2.1 MyBatis介绍​​​​​​​ 1. 入门案例 问题导入 MyBatisPlus环境搭建的步骤&#xff1f; 1.1 SpringBoot整合MyBatisPlus入门程序 ①&#xff1a;创建新模块&am…

P3368 【模板】树状数组 2

【模板】树状数组 2 题目描述 如题&#xff0c;已知一个数列&#xff0c;你需要进行下面两种操作&#xff1a; 将某区间每一个数加上 xxx&#xff1b; 求出某一个数的值。 输入格式 第一行包含两个整数 NNN、MMM&#xff0c;分别表示该数列数字的个数和操作的总个数。 第…

[Ext JS] Grid Summary(汇总行)特性

Ext.grid.feature.Summary 是 Grid 的feature之一。 这个特性会在表格的最下方多一行汇总。 汇总行主要包含两个部分: 值的计算效果的渲染使用后的效果如下: 定义方式 定义的步骤如下: 在grid的配置中使用features 加入 summary 的特性类型 ftype: summary在columns的每一列…

千峰学习【Ajax】总结

1.同步和异步 2.Ajax状态码 3.创建对象&#xff0c;发送请求 <script>//1.创建XHR&#xff1a; new XMLHttpRequest():var xhr new XMLHttpRequest();// console.log(xhr);//2&#xff0c;配置open(请求方式&#xff0c;请求地址&#xff0c;是否异步(默认为异步)) loc…

ESP32( IDF平台)+MAX30102 配合Pyqt上位机实现PPG波形显示与心率计算

0 引言 年前买了一个MAX30102模块&#xff0c;在家无聊做了这个demo对一些相关的知识进行学习。 主要学习的内容&#xff1a; 光体积变化描记图&#xff08;Photoplethysmogram, PPG&#xff09;测量原理学习。ESP32 IDF平台的MAX30102驱动开发&#xff0c;主要是初始化配置…

8、快捷键的使用

文章目录8、快捷键的使用8.1 常用快捷键第1组&#xff1a;通用型第2组&#xff1a;提高编写速度&#xff08;上&#xff09;第3组&#xff1a;提高编写速度&#xff08;下&#xff09;第4组&#xff1a;类结构、查找和查看源代码第5组&#xff1a;查找、替换与关闭第6组&#x…

理光M340W激光打印机加粉清零

粉盒型号&#xff1a; M340L&#xff08;如图&#xff09;&#xff1a; 加粉及清零&#xff1a; 原装粉盒不用考虑加粉了&#xff0c;原装粉盒墨粉用完后建议更换品牌代用的墨粉盒&#xff0c;品牌代用的墨粉盒直接带加粉口及清零齿轮&#xff1b; 1、加粉&#xff0c;打开加粉…

通信原理简明教程 | 物联网通信技术简介

文章目录1 物联网通信技术概述1.1 物联网通信的产生和发展1.2 物联网通信系统2 RFID技术2.1 RFID系统的组成2.2 RFID系统的工作原理2.3 RFID的典型应用3 ZigBee技术3.1 ZigBee技术的特点及应用3.2 ZigBee协议3.3 ZigBee网络的拓扑结构4 蓝牙通信技术4.1 蓝牙协议4.2 蓝牙网络连…

缓存失效问题和分布式锁引进

缓存失效问题 先来解决大并发读情况下的缓存失效问题&#xff1b; 1、缓存穿透  缓存穿透是指查询一个一定不存在的数据&#xff0c;由于缓存是不命中&#xff0c;将去查询数据库&#xff0c;但是数 据库也无此记录&#xff0c;我们没有将这次查询的 null 写入缓存&#x…

CNN中池化层的作用?池化有哪些操作?

(还没写完~) 一、What is 池化 1. 基本介绍 池化一般接在卷积过程后。池化,也叫Pooling,其本质其实就是采样,池化对于输入的图片,选择某种方式对其进行压缩,以加快神经网络的运算速度。这里说的某种方式,其实就是池化的算法,比如最大池化或平均池化。在卷积神经网络…

Linux常见命令 21 - 网络命令 ping、ifconfig、last、lastlog、traceroute、netstat

目录 1. 测试网络连通性 ping 2. 查看和设置网卡 ifconfig 3. 查看用户登录信息 last 4. 查看所有用户最后一次登录时间 lastlog 5. 查看数据包到主机间路径 traceroute 6. 显示网络相关信息 netstat 1. 测试网络连通性 ping 语法&#xff1a;ping [-c] IP地址&#xff0c…