数据结构——时间复杂度和空间复杂度

news2024/11/27 10:34:04

在这里插入图片描述
1.算法效率
2.时间复杂度
3.空间复杂度
4. 常见时间复杂度以及复杂度oj练习

1.算法效率
1.1 如何衡量一个算法的好坏

如何衡量一个算法的好坏呢?比如对于以下斐波那契数的计算

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

我们看到虽然用递归的方式实现斐波那契很简单,但是简单一定代表效率高吗?
我们接着往下看。
1.2 算法的复杂度
算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源 。因此衡量一个算法的好坏,一般
是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度。
时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需要的额外空间。在计算
机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计
算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。
1.3 复杂度在校招中的考察
在这里插入图片描述
我们可以看到在校招笔试的时候可能会遇到一些问题,就是它限制了时间和空间的复杂度,这无疑是加大了难度,所以我们现要了解什么是时间和空间复杂度,这样才能去写这道题。
2.时间复杂度
2.1 时间复杂度的概念
时间复杂度的定义:在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。一
个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知
道。但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个
分析方式。一个算法所花费的时间与其中语句的执行次数成正比例,算法中的基本操作的执行次数,为算法
的时间复杂度。
即:找到某条基本语句与问题规模N之间的数学表达式,就是算出了该算法的时间复杂度。
// 请计算一下Func1中++count语句总共执行了多少次?

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

通过我们的精确计算,count总共经过了N^2+2*N+M.
Func1 执行的基本操作次数 :
N = 10 F(N) = 130
N = 100 F(N) = 10210
N = 1000 F(N) = 1002010

所以当N特别大的时候后面可以忽略掉。
所以上面的代码的时间复杂度是O(N^2).

实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要大概执行次数,那么这
里我们使用大O的渐进表示法。

2.2 大O的渐进表示法
大O符号(Big O notation):是用于描述函数渐进行为的数学符号。
推导大O阶方法:
1、用常数1取代运行时间中的所有加法常数。
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。
使用大O的渐进表示法以后,Func1的时间复杂度为O(N^2).
通过上面我们会发现大O的渐进表示法去掉了那些对结果影响不大的项,简洁明了的表示出了执行次数。
另外有些算法的时间复杂度存在最好、平均和最坏情况:
最坏情况:任意输入规模的最大运行次数(上界)
平均情况:任意输入规模的期望运行次数
最好情况:任意输入规模的最小运行次数(下界)
例如:在一个长度为N数组中搜索一个数据x
最好情况:1次找到
最坏情况:N次找到
平均情况:N/2次找到
在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)

2.3常见时间复杂度计算举例

// 计算Func2的时间复杂度?
void Func2(int N)
{
	int count = 0;
	for (int k = 0; k < 2 * N; ++k)
	{
		++count;
	}
	int M = 10;
	while (M--)
	{
		++count;
	}
	printf("%d\n", count);
}

这个count的准确次数是2*N+M
所以写成大O是O(N)。

2

// 计算Func3的时间复杂度?
void Func3(int N, int M)
{
	int count = 0;
	for (int k = 0; k < M; ++k)
	{
		++count;
	}
	for (int k = 0; k < N; ++k)
	{
		++count;
	}
	printf("%d\n", count);
}

这里就要看前提是什么,如果不知道M和N的话,我们就可以写成O(M+N),如果M和N一样的话,可以写成O(N),如果N比M大的多,就可以写成O(N),反之则为O(M)。

// 计算Func4的时间复杂度?
void Func4(int N)
{
	int count = 0;
	for (int k = 0; k < 100; ++k)
	{
		++count;
	}
	printf("%d\n", count);
}

常数项其实就是O(1)因为我们的计算机的运行速度特别快,每秒十几亿的速度,所以常数项都可以写成O(1).

// 计算strchr的时间复杂度?
const char * strchr ( const char * str, int character );

在这里插入图片描述
意思就是找一个字符,有就返回字符位置,没有就返回空指针,所以这肯定要遍历一遍我们的字符串,所以是O(N)。

// 计算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;
	}
}

冒泡排序我们写的第一个是它的趟数,然后进行前后进行比较,如果有n个数,那第一次要比较的是n-1次,接下来,比如我们是升序的话,最后一个数就排好了,并且是最大的一个数,所以第二次就可以忽略最后一个数的比较,接下来就是n-2,这样下去一直到1,所以将他们相加,是(N^2-N)/2,当N无穷大的时候,所以大O就可以写成O(N*N).最快只需要n-1次就可以了

// 计算BinarySearch的时间复杂度?
int BinarySearch(int* a, int n, int x)
{
	assert(a);
	int begin = 0;
	int end = n - 1;
	while (begin < end)
	{
		int mid = begin + ((end - begin) >> 1);
		if (a[mid] < x)
			begin = mid + 1;
		else if (a[mid] > x)
			end = mid;
		else
			return mid;
	}
	return -1;
}

我们的二分查找时间复杂度可快了,是效率非常高的一个排序。
它的算法时间复杂度是O(log2N),可以写成logN,底数是2.
为什么说他快呢,举个例子,比如我们要在14亿人中要找出有个人,最坏情况只要31次,第一次直接去掉了7亿人,第二次又是一半,所以效率快。

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

其实它递归了N次,那就很简单,就是O(N)。

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

通过计算分析发现基本操作递归了2N次,时间复杂度为O(2N),因为我们第一次是2的1次,后面就是2的2次,一直到2的n次,相加就可写成O(2^N),所以递归并不是效率特别高的算法有时候,但是它简洁。

今天的分享就到这里,我们下次再见

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

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

相关文章

如何提高商城系统的稳定性?

电商行业的飞速发展&#xff0c;越来越多的企业开始关注电商建设。其中&#xff0c;商城系统的稳定性是企业最为关心的问题之一。 商城系统的稳定性不仅影响用户体验&#xff0c;还关系到企业的声誉和利益。因此&#xff0c;如何提高商城系统的稳定性是每一个电商企业必须要面对…

高忆管理:股票集合竞价?

股票集合竞价&#xff08;英文缩写为“SPAC”&#xff09;是股票商场开市前最终一个阶段&#xff0c;也被称为“开盘竞价”。在这个阶段&#xff0c;买卖双方能够提交订单&#xff0c;而且体系将会平衡对买卖盘进行撮合&#xff0c;以确认股票开盘价。这个阶段通常会在上午九点…

AnyCase4.0全球贸易集成平台震撼上线,免费试用赢取精美好礼!

全球贸易行业一直以来都面临着各种挑战和复杂的操作流程。然而&#xff0c;随着科技的不断进步和跨境贸易的日益发展&#xff0c;一个集物流服务、外贸服务、供应商管理和企业风控管理于一体的全新跨境贸易集成平台AnyCase4.0应运而生。经过多年的沉淀和精心打磨&#xff0c;An…

树结构转换

思路&#xff1a; 先把数组转化成一个对象&#xff08;map&#xff09;&#xff0c;对象的key值是对象的id 遍历对象&#xff1b;map[map[k].pid].children.push(map[k]),【k代表索引】&#xff0c;pid等于0代表是根节点 // 数结构转换let arr [{id: 1,pid: 0,name: "b…

【606. 根据二叉树创建字符串】

目录 1.题目描述2.算法思想3.代码实现 1.题目描述 这道题的重点其实就是要省去不影响映射的括号。如&#xff1a; 2.算法思想 3.代码实现 class Solution { public:string _tree2str(TreeNode* root,string& ret){if(rootnullptr){return "";}retto_string(ro…

考研不是在职提升的唯一的途径,还有免联考的社科院与杜兰大学金融管理硕士

社会的迅猛发展&#xff0c;职场竞争愈发激烈&#xff0c;许多人选择考研来提升自己的竞争力&#xff0c;因此考研人数也是逐年增加。根据研招网官方统计&#xff0c;2023年研究生报考人数为474万&#xff0c;相较去年22考研全国硕士研究生招生考试报名人数457万人&#xff0c;…

网盘直链下载助手

一、插件介绍 1.介绍 这是一款免费开源获取网盘文件真实下载地址的油猴脚本&#xff0c;基于 PCSAPI&#xff0c;支持 Windows&#xff0c;Mac&#xff0c;Linux 等多平台&#xff0c;支持 IDM&#xff0c;XDown&#xff0c;Aria2 等多线程下载工具&#xff0c;支持 JSON-RPC…

【网络模块】数传DTU(USR-DR150)进行MQTT通讯

文章目录 [TOC] 准备资料软件硬件硬件接线 USR-CAT1 V1.1.4配置 USR-DR15X 是一款有人物联网推出的“口红DTU”&#xff0c;也称为超小体积导轨式DTU&#xff0c;该产品具有体积小巧、集成SIM卡、蓝牙配置、导轨和挂耳安装方便的特征&#xff1b;Cat-1系列产品具备高速率、低延…

Windows使用docker desktop 安装kafka、zookeeper集群

docker-compose安装zookeeper集群 参考文章&#xff1a;http://t.csdn.cn/TtTYI https://blog.csdn.net/u010416101/article/details/122803105?spm1001.2014.3001.5501 准备工作&#xff1a; ​ 在开始新建集群之前&#xff0c;新建好文件夹&#xff0c;用来挂载kafka、z…

vue消息订阅与发布,实现任意组件间通讯

第一步&#xff1a;下载第三方消息订阅与发布库&#xff0c;例如常用的pubsub.js,他可以在任何框架中使用包括vue、react、anglar等等。 命令&#xff1a;npm i pubsub-js 注意是pubsub-js(不是点); 第二步&#xff1a;引入库&#xff1b; import pubsub from pubsub-js 第…

年之年的选择,组装版

组件&#xff1a;<!--* Author: liuyu liuyuxizhengtech.com* Date: 2023-02-01 16:57:27* LastEditors: wangping wangpingxizhengtech.com* LastEditTime: 2023-06-30 17:25:14* Description: 时间选择年 - 年 --> <template><div class"year-range-pick…

Tubi 前端测试:迁移 Enzyme 到 React Testing Library

前端技术发展迅速&#xff0c;即便不说是日新月异&#xff0c;每年也都推出新框架和新技术。Tubi 的产品前端代码仓库始建于 2015 年&#xff0c;至今 8 年有余。可喜的是&#xff0c;多年来紧随 React 社区的发展&#xff0c;Tubi 绝大多数的基础框架选型都遵循了社区流行的最…

一个php文件搞定微信小程序订阅消息推送(含access_token的获取、缓存、刷新)

摘要 微信小程序的订阅消息功能具有多个优点&#xff0c;可以为开发者和用户带来便利和更好的体验。以下是一些主要的优点&#xff1a; **个性化消息推送&#xff1a; **订阅消息允许开发者向用户发送个性化的消息内容&#xff0c;根据用户的偏好和行为进行定制化推送&#x…

设计模式(5)代理模式

一、介绍&#xff1a; 【Subject/抽象角色】定义了RealSubject和Proxy的共用接口&#xff0c;这样就可以在任何使用RealSubject的地方都可以使用Proxy 【RealSubject/真实角色】定义Proxy所代表的真实实体 【Proxy/代理角色】保存一个引用使得代理可以访问实体&#xff0c;并…

GIT结合Maven对源码以及jar包的管理建设

一、GIT管理规范 1.1 git分支概念 develop分支 开发分支,不管是要做新的feature还是需要做bug修复,都是从这个分支分出来做。 在这个分支下主要负责记录开发状态下相对稳定的版本,即完成了某个feature或者修复了某个bug后的开发稳定版本。 feature-*-*分支 feature-姓名…

CLION编译后的exe文件添加ico图标

编译前准备 1.编译ico.rc>ico.o 将图标放到工程目录下 新建ico.rc文件 id ICON "spoon.ico" //添加图标 #include <winver.h> VS_VERSION_INFO VERSIONINFOFILEVERSION 1,0,0,10PRODUCTVERSION 1,0,0,10FILEFLAGSMASK 0x3fL #ifdef _DEBUGFILEFLAGS VS_FF…

Vue-2.nodejs的介绍和安装

nodejs简介 ► 创建 Node.js 应用:package.json 首先&#xff0c;创建一个新文件夹以便于容纳需要的所有文件&#xff0c;并且在此其中创建一个 package.json 文件&#xff0c;描述你应用程序以及需要的依赖&#xff1a; 配合着你的 package.json 请运行 npm install。如果你…

企业权限管理(七)-权限操作

1. 数据库与表结构 1.1 用户表 1.1.1 用户表信息描述 users 1.1.2 sql语句 CREATE TABLE users( id varchar2(32) default SYS_GUID() PRIMARY KEY, email VARCHAR2(50) UNIQUE NOT NULL, username VARCHAR2(50), PASSWORD VARCHAR2(50), phoneNum VARCHAR2(20), STATUS INT )…

内网穿透是什么意思?快解析如何实现内网穿透

在家里或者公司&#xff0c;我们常常会使用路由器来连接网络&#xff0c;以便我们能够上网学习和工作&#xff0c;但有时候使用起来真的不方便。有的时候我们在外面&#xff0c;想访问家里或者公司内部的设备&#xff0c;就会碰到一个问题&#xff1a;我们无法直接通过公网IP访…

yolov5代码解读之yolo.py【网络结构】

​这个文件阿对于做模型修改、模型创新有很好大好处。 首先加载一些python库和模块&#xff1a; 如果要执行这段代码&#xff0c;直接在终端输入python yolo.py. yolov5的模型定义和网络搭建都用到了model这个类(也就是以下图片展示的东西)&#xff1a;&#xff08;以前代码没…