复杂度(7.23)

news2024/11/24 1:13:34

1.算法效率

如何衡量算法的好坏?

这里需要引入算法的复杂度

1.2算法的复杂度

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

2.时间复杂度

2.1时间复杂度的概念

时间复杂度的定义:在计算机科学中, 算法的时间复杂度是一个函数 ,它定量描述了该算法的运行时间。一个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知 道。但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个分析方式。一个算法所花费的时间与其中语句的执行次数成正比例, 算法中的基本操作的执行次数,为算法的时间复杂度
即: 找到某条基本语句与问题规模N之间的数学表达式,就是算出了该算法的时间复杂度。

例如:

// 请计算一下Func1中++count语句总共执行了多少次?
voidFunc1(intN)
{
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);
}
Func1 执行的基本操作次数:
是一个带未知数的表达式(函数),非c语言中的函数。
F(N)=N^2+2*N+10
实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要 大概执行次数,那么这 里我们使用 大O的渐进表示法
2.2 O 的渐进表示法
O 符号( Big O notation ):是用于描述函数渐进行为的数学符号。
推导大 O 阶方法:
1 用常数1取代运行时间中的所有加法常数
2 、在修改后的运行次数函数中, 只保留最高阶项。(决定结果项)
3 、如果最高阶项存在且不是 1 ,则去除与这个项目相乘的系数(常数)。得到的结果就是大 O 阶。
使用大 O 的渐进表示法以后, Func1 的时间复杂度为: O(N^2)

 我们容易看出最高阶项N^2起决定性作用,因此保留它。

2.3 常见时间复杂度计算举例
例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);
}

结果为 0(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(M+N),因为我们不知道M和N的大小关系(重要程度),因此不能去掉任意一方。

如果知道,那么

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

结果为O(1),常数次结果都写成O(1),即使常数为1万亿。(CPU运行速度足够快;数据类型的值有上限)

4:
// 计算strchr的时间复杂度?(str字符数组中查找一个字符)
const char * strchr ( const char * str, int character );
while(*str)
{

}
有些算法的时间复杂度例如此例存在最好、平均和最坏情况:
最坏情况:任意输入规模的最大运行次数 ( 上界 )
平均情况:任意输入规模的期望运行次数
最好情况:任意输入规模的最小运行次数 ( 下界 )
例如:在一个长度为 N 数组中搜索一个数据 x
最好情况: 1 次找到
最坏情况: N 次找到
平均情况: N/2 次找到
时间复杂度是一个稳健保守的预期, 在实际中一般情况关注的是算法的 最坏 运行情况,所以数组中搜索数据时间复杂度为O(N)
5:
// 计算冒泡排序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-1次,第二次n-2,第三次... ...,这是一个等差数列,用公式求n项和,为(N-1)*N/2,因此时间复杂度为O(N^2)。

6:
// 计算二分(折半)查找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;
}

二分查找的原理:

该数列是有序的,从中间位置开始查找,如果要找的值更大或更小,就缩小一半查找范围,缩小一次,下一次查找的数量就除2,那么除了多少次2就查找了多少次

查找区域只剩一个值为最坏情况,假设查找x次,2^x=N,x=log2N。

只有以2为底求n的对数可以写成logN

二分查找和暴力查找之间的效率差距是巨大的,二分查找的效率非常高,但限制在于每次插入删除都需要重新排序。

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

总结:递归调用是多次调用的次数的累加

从Fac(N)到Fac(0)进行了N-1次调用,为常数次,因此结果为O(N)。

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

 F(N)=2^0+2^1+2^2+2^3+... ...+2^(N-1)

=2^N-1

2^N

面试题

消失的数字

思路1:排序+遍历(下一个数不等于这一个数+1,这个数就是消失的数字)

时间复杂度:O(logN*N) (不符合)

思路2:0-N等差数列公式计算N项和-数组中值的和,就是消失的数字

时间复杂度:O(N)(符合)

思路3:单身狗(异或)

时间复杂度:O(N)(符合)

相同为0,相异为1,相同的数只要放在一块进行了异或,就为0,与顺序无关

那么将原数组和有缺失的数组放在一起异或,结果就为消失的数。

 思路2实现:

//参数为数组指针和成员数量
int MissingNumber(int* nums, int numSize)
{
	int N = numSize;
	//求和公式求出N项和
	int ret = N*(1 + N) / 2;
	int i = 0;
	for (i = 0; i < N; i++)
	{
		//减去数组中的成员
		ret -= nums[i];
	}
	return ret;
}

思路3实现:

int MissingNumber(int* nums, int numSize)
{
	int N = numSize;
	//用来存放异或结果的容器
	int x = 0;
	//将原数组放进容器
	for (int i = 0; i <= N; i++)
	{
		x ^= i;
	}
	//将有缺失的数组放进去一起异或
	for (int i = 0; i < N; i++)
	{
		//得到缺失值
		x ^= nums[i];
	}
	return x;
}
int main()
{
	int arr[5] = { 0,1,2,4,5 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("%d\n", MissingNumber(arr, sz));

	return 0;
}

 

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

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

相关文章

docker 安装 nessus新版、awvs15-简单更快捷

一、docker 安装 nessus 参考项目地址&#xff1a; https://github.com/elliot-bia/nessus 介绍&#xff1a;几行代码即可一键安装更新 nessus -推荐 安装好 docker后执行以下命令 #拉取镜像创建容器 docker run -itd --nameramisec_nessus -p 8834:8834 ramisec/nessus …

Cisco Packet Tracer的下载与安装+汉化

一、下载 1、思科官网下载 参考连接&#xff1a;Cisco Packet Tracer - Networking Simulation Tool (netacad.com) 2、百度网盘 链接&#xff1a;https://pan.baidu.com/s/18xzqdACkCXngMzYm5UV_zg 提取码&#xff1a;xuyi 二、安装 双击安装包 点击下一步 选择同意条款&…

VUE指令语法解析标签属性

我们可以在标签体中使用插值语法 {{ }} 来直接读取data中的属性 那我们能使用相同的方法将我们的网址给填入a标签的href属性中吗&#xff1f; 我们运行后会发现并没有给我们变为<a href"https://blog.csdn.net/XunLin233">&#xff0c;而是<a href"{{…

个性化定制企业邮件域名的解决方案

随着互联网的快速发展&#xff0c;电子邮件已经成为了商业沟通的主要方式之一。而企业邮箱作为企业进行正式商务交流的重要工具&#xff0c;其域名和后缀的选择也引起了人们的关注。其中一个关键的问题是&#xff1a;企业邮箱的后缀是否可以自定义&#xff1f;企业邮箱的后缀是…

MSF的安装与使用教程,超详细,附安装包和密钥

MSF简介 Metasploit&#xff08;MSF&#xff09;是一个免费的、可下载的框架 它本身附带数百个已知软件漏洞&#xff0c;是一款专业级漏洞攻击工具。 当H.D. Moore在2003年发布Metasploit时&#xff0c;计算机安全状况也被永久性地改变了&#xff0c;仿佛一夜之间&#xff0…

ipad触控笔有必要买原装吗?性价比触控笔排行榜

随着社会经济的发展&#xff0c;越来越多的人需要用到电容笔。国产的平替电器笔&#xff0c;与苹果原装的电容笔差别并不大&#xff0c;无论是在功能上&#xff0c;还是在触感上&#xff0c;都相差无几&#xff0c;写起字来更是行云流水&#xff0c;让我有些意外的是&#xff0…

el-upload实现复制粘贴图片

前言&#xff1a; 在之前的项目中&#xff0c;利用el-upload实现了上传图片视频的预览。项目上线后&#xff0c;经使用人员反馈&#xff0c;上传图片、视频每次要先保存到本地然后再上传&#xff0c;很是浪费时间&#xff0c;公司客服人员时间又很紧迫&#xff08;因为要响应下…

Xmake v2.8.3 发布,改进 Wasm 并支持 Xmake 源码调试

Xmake 是一个基于 Lua 的轻量级跨平台构建工具。 它非常的轻量&#xff0c;没有任何依赖&#xff0c;因为它内置了 Lua 运行时。 它使用 xmake.lua 维护项目构建&#xff0c;相比 makefile/CMakeLists.txt&#xff0c;配置语法更加简洁直观&#xff0c;对新手非常友好&#x…

描述性统计分析

前言&#xff1a; 本专栏参考教材为《SPSS22.0从入门到精通》&#xff0c;由于软件版本原因&#xff0c;部分内容有所改变&#xff0c;为适应软件版本的变化&#xff0c;特此创作此专栏便于大家学习。本专栏使用软件为&#xff1a;SPSS25.0 本专栏所有的数据文件可在个人主页—…

电脑D盘格式化会有什么影响?电脑D盘格式化了怎么恢复数据

当电脑出现问题时&#xff0c;往往会出现一些提示&#xff0c;例如提示格式化的问题&#xff0c;而最近有位小伙伴也遇到了相似的问题&#xff0c;即D盘一打开就显示格式化&#xff0c;由于不清楚D盘格式化会有什么影响&#xff0c;因此不小心进行了格式化操作&#xff0c;结果…

较真儿学源码系列-PowerJob启动流程源码分析

PowerJob版本&#xff1a;4.3.2-main。 1 简介 PowerJob是全新一代的分布式任务调度与计算框架&#xff0c;官网地址&#xff1a;http://www.powerjob.tech/。其中介绍了PowerJob的功能特点&#xff0c;以及与其他调度框架的对比&#xff0c;这里就不再赘述了。 以上是PowerJob…

基于PSO算法的功率角摆动曲线优化研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

MySQL的执行流程

在聊mysql的执行流程之前&#xff0c;咱们要先聊聊mysql的逻辑架构。 逻辑架构 可以将上图简化为下图 连接层 客服端访问mysql服务器前&#xff0c;要先和mysq建立tcp连接。经过3次握手建立连接成功后&#xff0c;mysql服务器对tcp传输过来的账号密码进行身份认证&#x…

接口测试之文件下载

在工作中对于下载接口&#xff0c;经常会有这样的疑问&#xff1a;这类接口一般功能比较稳定&#xff0c;但是又比较重要&#xff0c;需要占用回归测试时间&#xff0c;有没有可替代的方式&#xff1f; 答案肯定是有的&#xff0c;可以从接口测试/UI自动化测试介入&#xff0c;…

UE5 虚幻引擎 使用编辑器工具进行资产批处理操作 让你的工作效率指数级增长!!!

目录 0 引言1 编辑器工具蓝图1.1 介绍1.2 案例&#xff1a;批量设置静态网格体资产的LOD1.3 进阶用法 2 编辑器工具控件2.1 介绍2.2 案例&#xff1a;随机给场景中Actor添加Yaw旋转值 0 引言 官方教程视频 参考文章 参考视频 UE5提供了两种 编辑器工具 &#xff1a;编辑器工具…

Dubbo学习(二)——dubbo环境搭建

文章目录 dubbo核心简介SpringCloud与Dubbo的区别Dubbo的架构说明dubbo和Feign远程调用的差异共同点&#xff1a;区别&#xff1a; 基于 Spring Boot 开发微服务应用项目介绍1. 启动注册中心2. 新建一个spring boot项目3. 添加 Maven 依赖4. 定义服务接口5. 定义服务端的实现实…

操作系统 --- 进程的描述与控制

&#xff08;一 &#xff09;前趋图和程序的执行 前趋图 前趋图 :有向无循环图 &#xff0c;用于描述 进程之间执行的先后顺序 结点表示进程或程序段&#xff0c;有向边表示前趋关系 前驱图中是不允许有循环的&#xff0c;否则必然会产生无法实现的前驱关系。 &#xff08;二…

浙大公共管理硕士(MPA)提前批面试的题库里到底有哪些内容?

像研究生招生这样严肃的工作&#xff0c;所有的环节和程序都得有章可循&#xff01;浙大公共管理硕士&#xff08;MPA&#xff09;项目提前批面试即将在10月14日举行&#xff0c;已经通过材料审核的考生肯定很想知道面试中会遇到什么样的题目&#xff0c;专注浙大的杭州达立易考…

卤制品配送经营商城小程序的用处是什么

卤制品也是食品领域重要的分支&#xff0c;尤其对年轻人来说&#xff0c;只要干净卫生好吃价格合理&#xff0c;那复购率宣传性自是不用说&#xff0c;而随着互联网发展&#xff0c;传统线下门店也须要通过线上破解难题或进一步扩大生意。 而商城小程序无疑是商家通过线上私域…

Redis各数据类型特定的命令和用法 1.0版本

目录 一、Sring数据类型1.1 概述1.2 set/get/append/strlen命令1.3 incr/decr/incrby/decrby 命令1.4 getset命令1.5 setex命令1.6 setnx命令1.7 mset/mget/msetnx命令 二、List数据类型2.1 概述2.2 lpush/lpushx/lrange命令2.3 lpop/llen命令2.4 lrem/lset/lindex/ltrim命令2.…