数据结构与算法-时间复杂度与空间复杂度

news2024/11/19 23:23:56

数据结构与算法

  • 🎈1.概论
    • 🔭1.1什么是数据结构?
    • 🔭1.2什么是算法?
  • 🎈2.算法效率
    • 🔭2.1如何衡量一个算法的好坏?
    • 🔭2.2算法的复杂度
    • 🔭2.3时间复杂度
      • 📖2.3.1时间复杂度的概念
      • 📖2.3.2大O的渐进表达式
      • 📖2.3.3常见时间复杂度计算举例
    • 🔭2.4空间复杂度
    • 🔭2.5常见复杂度对比

🎈1.概论

🔭1.1什么是数据结构?

数据结构是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合。

🔭1.2什么是算法?

算法就是定义良好的计算过程,他取一个或一组的值为输入,并产生一个或一组值作为输出。简单来说算法就是一系列的计算步骤,用来将输入数据转化成输出结果。

🎈2.算法效率

🔭2.1如何衡量一个算法的好坏?

算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源。因此衡量一个算法的好坏,一般是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度。

🔭2.2算法的复杂度

时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需要的额外空间。 在计算机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。

🔭2.3时间复杂度

📖2.3.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;
	}
	printf("%d\n", count);
}

在这里插入图片描述

  • N = 10 F(N) = 130
  • N = 100 F(N) = 10210
  • N = 1000 F(N) = 1002010

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

📖2.3.2大O的渐进表达式

大O符号(Big O notation):是用于描述函数渐进行为的数学符号。
推导大O阶方法:

  • 用常数1取代运行时间中的所有加法常数。
  • 在修改后的运行次数函数中,只保留最高阶项。
  • 如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。

使用大O的渐进表示法以后,Func1的时间复杂度为:O(N2)

  • N = 10 F(N) = 100
  • N = 100 F(N) = 10000
  • N = 1000 F(N) = 1000000

通过上面我们会发现大O的渐进表示法去掉了那些对结果影响不大的项,简洁明了的表示出了执行次数。

📖2.3.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);
}

使用大O的渐进表示法以后,Func2的时间复杂度为:O(N)

✅示例三:

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

使用大O的渐进表示法以后,Func3的时间复杂度为:O(M+N)

✅示例四:

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

使用大O的渐进表示法以后,Func4的时间复杂度为:O(1)

✅示例五:

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

本函数是用来在一个字符串中找出某个字符的,那么假设我们这里的字符串是hello world
如果我们需要查找的是h,那么我们只需要查找1次,这也称为最好情况,即任意输入规模的最小运行次数。
如果我们需要查找的是w,那么我们只需要查找N/2次,这也称为平均情况,即任意输入规模的期望运行次数。
如果我们需要查找的是d,那么我们只需要查找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;
	}
}

使用大O的渐进表示法以后,Func6的时间复杂度为:O(N2)

✅示例七:

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

使用大O的渐进表示法以后,Func7的时间复杂度为:O(logN)

✅示例八:

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

使用大O的渐进表示法以后,Func8的时间复杂度为:O(2N)

✅示例九:

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

使用大O的渐进表示法以后,Func9的时间复杂度为:O(N)

🔭2.4空间复杂度

空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度 。
空间复杂度不是程序占用了多少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;
	}
}

使用大O的渐进表示法以后,示例1的空间复杂度为: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;
}

使用大O的渐进表示法以后,示例2的空间复杂度为:O(N)

✅示例3:

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

使用大O的渐进表示法以后,示例3的空间复杂度为:O(N)
在这里插入图片描述
✅示例4:

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

使用大O的渐进表示法以后,示例4的空间复杂度为:O(N)

空间是可以重复利用的,不累计的;时间是一去不复返的,累计的。

🔭2.5常见复杂度对比

执行次数函数非正式术语
3O(1)常数阶
2n+1O(n)线性阶
3n2+2n+1O(n2)平方阶
3log2n(2为底数)+2O(logn)对数阶
n+4nlog2n(2为底数)+7O(nlogn)nlogn阶
5n3+3n2+2n+1O(n3)立方阶
2nO(2n)指数阶

常用时间复杂度所消耗时间从小到大依次是:O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)

在这里插入图片描述

好啦,关于复杂度的知识点到这里就结束啦,后期会继续更新数据结构与算法的相关知识,欢迎大家持续关注、点赞和评论!❤️❤️❤️

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

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

相关文章

Oracle 12c自动化管理特性的新进展:自动备份、自动恢复和自动维护功能的优势|oracle 12c相对oralce 11g的新特性(3)

一、前言: 前面几期讲解了oracle 12c多租户的使用、In-Memory列存储来提高查询性能以及数据库的克隆、全局数据字典和共享数据库资源的使用 今天我们讲讲oracle 12c的另外的一个自动化管理功能新特性:自动备份、自动恢复、自动维护的功能 二、自动备份、自动恢复、自动维护…

新思路,4.9+氧化应激相关基因构建风险模型

今天给同学们分享一篇氧化应激预后模型的生信文章“Construction of an oxidative stress-related lncRNAs signature to predict prognosis and the immune response in gastric cancer”&#xff0c;这篇文章于2023年5月31日发表在Scientific Reports期刊上&#xff0c;影响因…

【LeetCode】——双指针(快慢指针)/多指针

个人主页 代码仓库 C语言专栏 初阶数据结构专栏 Linux专栏 前言 大家好&#xff01;这是新开的LeetCode刷题专栏&#xff0c;这个专栏不只是随便的拿一些我练过的题讲解&#xff0c;而是总结我在刷题中的一些方法适用于一大类的题&#xff0c;是给大家提供这一大类题的解题…

STL-函数对象、谓词、常用算法

函数对象 函数对象概念 重载函数调用操作符的类&#xff0c;其对象常称为函数对象 函数对象使用重载的()时&#xff0c;行为类似函数调用&#xff0c;也叫仿函数 本质&#xff1a; 函数对象&#xff08;仿函数&#xff09;是一个类&#xff0c;不是一个函数 函数对象使用…

第一章:最新版零基础学习 PYTHON 教程(第十节 - Python 语句中的 – Python 如果否则)

在现实生活中,有时我们需要做出一些决定,并根据这些决定来决定下一步应该做什么。在编程中也会出现类似的情况,我们需要做出一些决定,并根据这些决定我们将执行下一个代码块。编程语言中的决策语句决定了程序执行流程的方向(控制流)。 Python 中的控制流类型 在Python…

计算π的近似值分数 ——python

利用格里高利公式&#xff1a; 计算 的近似值&#xff0c;直到最后一项的绝对值小于给定精度eps。 输入格式: 输入小于1且大于0的阈值。 输出格式: 输出满足阈值条件的近似圆周率&#xff0c;输出到小数点后6位。 输入样例: 在这里给出一组输入。例如&#xff1a; 0.0…

基于Quartz的可视化UI操作组件GZY.Quartz.MUI更新说明(附:在ABP中集成GZY.Quartz.MUI可视化操作组件)

NET Core 基于Quartz的UI可视化操作组件 GZY.Quartz.MUI 简介 像swaggerUI一样,项目入侵量小,仅需要在Startup中注入的UI组件 先上一张效果图,给没用过的兄弟们科普一下,如图: 更新内容 接下来,介绍一下更新了哪些功能. 1.修复采用数据库持久化数据的情况下,偶尔出现的异常…

一、vue2的基础语法巩固

一、定义&#xff1a;是一个渐进式的JavaScript框架 二、特点&#xff1a; 减少了大量的DOM操作编写 &#xff0c;可以更专注于逻辑操作分离数据和界面的呈现&#xff0c;降低了代码耦合度(前端端分离)支持组件化开发&#xff0c;更利于中大型项目的代码组织 vue2核心功能&a…

NIO简单介绍

一、什么是NIO 1、Java NIO全称java non-blocking IO&#xff0c; 是指JDK提供的新API。从JDK1.4开始&#xff0c;Java提供了一系列改进的输入/输出的新特性&#xff0c;被统称为NIO(即New IO)&#xff0c;是同步非阻塞的 2、NIO有三大核心部分: Channel(通道)&#xff0c; Buf…

2023-9-23 区间覆盖

题目链接&#xff1a;区间覆盖 #include <iostream> #include <algorithm>using namespace std;const int N 100010;int n; struct Range {int l, r;bool operator< (const Range &W) const{return l < W.l;} }range[N];int main() {int st, ed;cin >…

Mybatis-Flex框架初体验

本篇文章内容主要包括&#xff1a; MyBatis-Flex 介绍 MyBatis-Flex 是一个优雅的 MyBatis 增强框架&#xff0c;它非常轻量、同时拥有极高的性能与灵活性。我们可以轻松的使用Mybaits-Flex链接任何数据库&#xff0c;其内置的QueryWrapper亮点帮助我们极大的减少了SQL编写的工…

SpringBoot3项目中配置JDK17

概述 SpringBoot3需要JDK17的支持&#xff0c;不再支持JDK8。 如果要运行SpringBoot3的项目&#xff0c;根据使用的IDE&#xff0c;需要的配置不同。 配置说明 1. SpringToolSuite4 如果使用的是SpringToolSuite4&#xff08;STS&#xff09;&#xff0c;比较简单&#xf…

Linux 链表示例 LIST_INIT LIST_INSERT_HEAD

list(3) — Linux manual page 用Visual Studio 2022创建CMake项目 * CmakeLists.txt # CMakeList.txt : Top-level CMake project file, do global configuration # and include sub-projects here. # cmake_minimum_required (VERSION 3.12)project ("llist")# I…

法线贴图的视线原理

在上一篇文章中详细介绍了位移贴图的相关知识&#xff0c;在本章中我们继续讲述法线贴图的相关概念&#xff0c;文章后面继续用GLTF 编辑器 来演示下法线贴图的模型渲染效果。 1、什么是法线贴图 法线贴图&#xff08;Normal Map&#xff09;是一种纹理映射技术&#xff0c;用…

Vivado 综合属性之use_dsp48

use_dsp48综合属性提示综合工具如何处理算术运算的实现结构&#xff1b;在默认的情况下&#xff0c;如下的算术类型结构会综合成DSP48E资源&#xff1b; MultMult-add&Mult-subMult-accumulate 而adders&#xff0c;subtracters&#xff0c;与accumulators在默认情况下会使…

安装Linux虚拟机——以ubuntukylin-16.04.7-desktop-amd64.iso为例

正文 安装VMware 重要提示 安装软件之前&#xff0c;请先退出360、电脑管家等安全类软件&#xff0c;这类软件会阻止我们安装的软件进行注册表注册&#xff0c;很可能导致安装失败。确认物理机&#xff08;也就是你自己使用的电脑&#xff09;的防火墙已经关闭。 下载 打开…

23062day4

制作一个简易圆形时钟 头文件&#xff1a; #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPaintEvent> #include <QDebug> #include <QPainter> #include <QTimerEvent> #include <QTime> #include <QThread> …

vue重修002

文章目录 版权声明一 指令修饰符1. 什么是指令修饰符&#xff1f;2. 按键修饰符3. v-model修饰符4. 事件修饰符 二 v-bind对样式控制的增强-操作class1. 语法&#xff1a;2. 对象语法3. 数组语法4. 代码练习 三 京东秒杀-tab栏切换导航高亮四 v-bind对有样式控制的增强-操作sty…

同源策略和跨域问题的解决

跨域问题 跨域问题顾名思义是当浏览器对不同于当前域的一个域下的资源进行访问和操作而产生的一系列**问题。**这些限制问题的产生是因为浏览器出于安全考虑对同源请求放行&#xff0c;对异源请求限制的一种规则&#xff0c;这种规则就是同源策略&#xff0c;因此限制造成的开…

【AI视野·今日NLP 自然语言处理论文速览 第三十八期】Thu, 21 Sep 2023

AI视野今日CS.NLP 自然语言处理论文速览 Thu, 21 Sep 2023 Totally 57 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers Chain-of-Verification Reduces Hallucination in Large Language Models Authors Shehzaad Dhuliawala, Mojt…