C语言学习第二十六天(算法的时间复杂度和空间复杂度)

news2024/11/27 6:23:24

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

在实际计算时间复杂度的时候,不一定要精确计算出执行次数,我们只需要找到其中主导时间复杂度的式子​​​​​​​,这里需要使用大O的渐进表示法

大O的渐进表示法:

1、用常数1取代运行时间中的所有加法常数

2、在修改后的运行次数函数中,只保留最高阶项

3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果是大O阶

所以上面的Func1函数的时间复杂度是O(N^2)

还有一种情况是需要注意的:当有些算法在不同的情况之下执行的次数不同,我们取得是其最坏的情况,比如这个算法的执行次数可以是1  \frac{N}{2}  N,我们取其最坏的情况,所以时间复杂度是O(N)。

下面举一些计算时间复杂度的例子,以供大家参考

例1:

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

首先进入第一个for循环,可见这个for循环要执行2N次,然后在进入下面的while循环,执行10次,一共就是10+2N次,根据上面说的时间复杂度计算方法,为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);
}

这个还是比较容易看出,时间复杂度是O(N+M)。

例3:

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

这个中间的for循环被执行了100次,由上述规则,可知其时间复杂度是O(1)

例4:

// 计算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)+...+1=\frac{(n+1)*n}{2} ,根据上面的时间复杂度的计算方式,为O(N^{2})。

例5:

// 计算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(log n)。

例6:

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

 return Fac(N-1)*N;
}

这个例子中,递归了N次,所以其时间复杂度是O(N)

例7:

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

 return Fib(N-1) + Fib(N-2);
}

这个例子递归了N^{2}次,所以时间复杂度是O(N^{2}).

3、空间复杂度

解释:这是对一个算法在运行过程中临时占用存储空间大小的量度

需要注意的是:空间复杂度是计算的变量的个数,这个计算方法也是使用的大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)。

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

这个开辟了N个空间,所以空间复杂度是O(N),

例3:

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

 return Fac(N-1)*N;
}

递归调用了N次,开辟了N个栈帧,每个栈帧使用了常数个空间。空间复杂度为O(N)

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

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

相关文章

面试 Java 算法高频题五问五答第一期

面试 Java 算法高频题五问五答第一期 作者&#xff1a;程序员小白条&#xff0c;个人博客 相信看了本文后&#xff0c;对你的面试是有一定帮助的&#xff01; ⭐点赞⭐收藏⭐不迷路&#xff01;⭐ 1&#xff09;括号生成: 数字 n 代表生成括号的对数&#xff0c;请你设计一个…

neuq-acm预备队训练week 10 P1129 [ZJOI2007] 矩阵游戏

题目描述 小 Q 是一个非常聪明的孩子&#xff0c;除了国际象棋&#xff0c;他还很喜欢玩一个电脑益智游戏――矩阵游戏。矩阵游戏在一个 nn 黑白方阵进行&#xff08;如同国际象棋一般&#xff0c;只是颜色是随意的&#xff09;。每次可以对该矩阵进行两种操作&#xff1a; 行…

STM32F103RCT6开发板M3单片机教程04--按键检测

原画图讲解 本教程使用是&#xff08;光明谷SUN_STM32mini开发板&#xff09; 首先了硬件连接原理&#xff0c;STM32F103RCT6开发板是mini最小系统板&#xff0c;板子在没并有按键。需要自行用面包板搭建。 硬件连接&#xff1a; PC10 -> KEY1 &#xff08;MCU内部上拉…

创投课程第五期 | 超越比特币:探索BTC生态的无限可能

协会邀请了来自水滴资本&#xff08;Waterdrip Capital&#xff09;的投资总监——Elaine&#xff0c;作为VC创投课程第5期的嘉宾&#xff0c;在北京时间12月17日(周日)晚上21:00 PM-22:00 PM&#xff0c;届时将与所有对Web3投资、创业心怀热忱的朋友们共同探讨《超越比特币&am…

TCP/IP详解——DNS 流量分析

文章目录 1. DNS 流量分析1.1 DNS 基本概念1.2 DNS 系统特性1.3 DNS 效率问题1.4 域名的组成1.5 域名解析系统1.5.1 域名解析过程 1.6 DNS 记录种类1.7 DNS 的报文格式1.7.1 DNS 报文中的基础结构部分1.7.2 DNS 查询报文中的问题部分1.7.3 DNS 响应报文中的资源记录部分1.7.4 示…

Unity中URP下的菲涅尔效果实现(个性化修改)

文章目录 前言一、我们修正一下上篇文章中&#xff0c;可能遗留的Bug1、N向量 变为 单位向量2、使颜色范围在合理区间 二、实现菲涅尔效果强弱可自定义调节三、修改菲涅尔效果颜色1、在属性面板定义颜色属性2、在常量缓冲区申明该参数3、在片元着色器中&#xff0c;用颜色和菲涅…

数据结构 AVL树概念以及实现插入的功能(含Java代码实现)

为啥要有avl树 avl树是在二叉搜索树下的一种进阶形式,是为了防止二叉搜索树在极端情况下产生的链表化的场景,从而在二叉搜索树的基础上,加上了某些条件来阻止这种极端情况的产生,但不是保证完全平衡,而是放开了一定的条件,使得这种情况不那么难以满足.(条件:左右子树的高度差的…

【Vulnhub 靶场】【IA: Keyring (1.0.1)】【中等】【20210730】

1、环境介绍 靶场介绍&#xff1a;https://www.vulnhub.com/entry/ia-keyring-101,718/ 靶场下载&#xff1a;https://download.vulnhub.com/ia/keyring-v1.01.ova 靶场难度&#xff1a;中等 发布日期&#xff1a;2021年07月30日 文件大小&#xff1a;1.1 GB 靶场作者&#xf…

Day63力扣打卡

打卡记录 寻找最近的回文数&#xff08;模拟&#xff09; 链接 class Solution:def nearestPalindromic(self, n: str) -> str:m len(n)candidates [10 ** (m - 1) - 1, 10 ** m 1]selfPrefix int(n[:(m 1) // 2])for x in range(selfPrefix - 1, selfPrefix 2):y …

ArcMap自定义脚本工具箱迁移至ArcGIS pro

本文记录了将ArcMap10.7创建的自定义脚本工具箱&#xff08;.tbx&#xff09;迁移至ArcGIS pro的过程 ArcGIS Pro使用的是python版本与ArcMap不同&#xff0c;前者为python3&#xff0c;后者为python2。由于python3 和 python2 的部分语法不兼容&#xff0c;以及一些地理处理工…

性能测试之Artillery(示例及指标)

官方文档&#xff1a;https://www.artillery.io/docs/get-started/first-test PS:文档挺详细&#xff0c;教程比较全 示例 config:http:extendedMetrics: truetarget: http://127.0.0.1:8005phases:- duration: 10 # 持续时间arrivalRate: 10 # 每秒创建10个用户rampTo: 100 …

【漏洞复现】CVE-2023-6848 kodbox远程命令执行

漏洞描述 kodbox 是一个网络文件管理器。它也是一个网页代码编辑器,允许您直接在网页浏览器中开发网站。您可以在基于 Linux、Windows 或 Mac 的平台上在线或本地运行 kodbox。唯一的要求是要有 PHP 5及以上。 kalcaddle kodbox 中发现漏洞,最高版本为 1.48。它已被宣布为关…

LV.13 D5 uboot概述及SD卡启动盘制作 学习笔记

一、uboot概述 1.1 开发板启动过程 开发板上电后首先运行SOC内部iROM中固化的代码(BL0)&#xff0c;这段代码先对基本的软硬件环境(时钟等...)进行初始化&#xff0c;然后再检测拨码开关位置获取启动方式&#xff0c;然后再将对应存储器中的uboot搬移到内存&#xff0c;然后跳…

目标跟踪 MOT数据集和可视化

目录 MOT15数据集格式简介 gt可视化 本人修改的GT可视化代码&#xff1a; MOT15数据集格式简介 以下内容转自&#xff1a;【目标跟踪】MOT数据集GroundTruth可视化-腾讯云开发者社区-腾讯云 MOT15数据集下载&#xff1a;https://pan.baidu.com/s/1foGrBXvsanW8BI4eybqfWg?…

机器学习算法---时间序列

类别内容导航机器学习机器学习算法应用场景与评价指标机器学习算法—分类机器学习算法—回归机器学习算法—聚类机器学习算法—异常检测机器学习算法—时间序列数据可视化数据可视化—折线图数据可视化—箱线图数据可视化—柱状图数据可视化—饼图、环形图、雷达图统计学检验箱…

vue3中ref及reactive的说明

目录 1.响应式说明 2.vue3的ref及reactive的使用 3.reactive响应式失效问题 4.总结 1.响应式说明 vue的响应式是vue框架中的核心概念之一&#xff0c;它是指当数据发生变化时&#xff0c;vue能够自动更新视图。vue2的响应式是基于Object.defineProperty进行实现的。 当你把…

安全密码(字符串)

#include <stdio.h> #include <stdbool.h> #include <string.h> bool is_secure_password(const char* password); int main() {int M;char password[51];// 读取输入中的密码数量 Mscanf("%d", &M);// 处理每个密码for (int i 0; i < M; …

智慧校园2.0物联网管理平台建设方案:PPT全文22页,附下载

关键词&#xff1a;物联网解决方案&#xff0c;智慧校园解决方案&#xff0c;物联网平台建设方案&#xff0c;物联网应用技术 一、智慧校园2.0物联网管理平台建设背景 1、教育现代化和强国建设的需要&#xff1a;近年来&#xff0c;国家为了加快推进教育现代化、教育强国建设…

OpenSergo Dubbo 微服务治理最佳实践

*作者&#xff1a;何家欢&#xff0c;阿里云 MSE 研发工程师 Why 微服务治理&#xff1f; 现代的微服务架构里&#xff0c;我们通过将系统分解成一系列的服务并通过远程过程调用联接在一起&#xff0c;在带来一些优势的同时也为我们带来了一些挑战。 如上图所示&#xff0c;可…

Eclipse 自动生成注解,如果是IDEA可以参考编译器自带模版进行修改

IDEA添加自动注解 左上角选择 File -> Settings -> Editor -> File and Code Templates&#xff1b; 1、添加class文件自动注解&#xff1a; ​/*** <b>Function: </b> todo* program: ${NAME}* Package: ${PACKAGE_NAME}* author: Jerry* date: ${YEA…