复杂度的讲解

news2024/11/20 21:16:40

1.算法效率

如何衡量一个算法的好坏?从两个维度,时间和空间(算法运行的快慢,消耗的空间大不大)。因为计算机硬件领域的高速发展,如今计算机的存储量已经达到了一个很高的程度,所以现在我们一般重点关注时间复杂度,空间复杂度也就不那么被重视了。

2.时间复杂度

时间复杂度的定义:在计算机科学中,算法的时间复杂度是一个函数表达式(数学意义上的函数)。时间复杂度描述的不是算法运行的具体时间,因为一个程序的时间是没有标准的,他跟计算机的硬件有很大的关系,而一个算法的运行时间与其中语句的执行次数是成正比例的,所以时间复杂度描述的是算法中的基本操作的执行次数。

找到某条基本语句和问题规模N之间的数学表达式,就是算出了该算法的时间复杂度。比如下面这段代码:

void test(int N)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < N; i++)
	{
		for (j = 0; j < i; j++)
		{
			printf("* ");
		}
		printf("\n");
	}
}

这个算法的基本语句就是循环中的打印星号和打印换行,打印星号的执行的次数是(0+1+2+……+N-1)=N(N-1)/2,而打印换行的执行次数为N次,所以这个算法的时间复杂度为N(N+1)/2。但是我们一般不需要准确的执行次数,只需要知道大概的次数就行了,于是就有了一种大O的渐进表示法。比如这个算法,我们一般描述它的时间复杂度就是O(N^2)

大O的渐进表示法的规则:

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

2.在修改后的运行次数追踪,只保留最高阶

3.如果最高阶项系数存在且不为1,则去除这个项的常数系数。

如果表达式结果是常数,那就是O(1)

就比如上面的算法,准确的运行次数是N^2/2+N/2,首先去除加法常数,因为没有,所以不用管。如何只保留最高阶,也就是N^2/2,最高阶地系数为1/2,把系数去除,得到的就是N^2,时间复杂度就是O(N^2)。

只保留最高项是因为这个最高项是对结果产生决定性影响,就比如N^2+N,当N接近无穷大时,N^2的结果才是决定最终结果的关键因素,而N在这里起到的效果几乎可以忽略不记。

为什么最高项常数系数要去除呢?还是因为N趋近无穷大时,由于这个常数系数不管多大他都是远小于无穷大的,不会对最终结果产生太大影响,至少不会在量级上产生大的影响。

再比如下面这个算法:

int fib(int n)
{
	if (n == 1 || n == 2)
	{
		return 1;
	}
	else
	{
		return fib(n - 1) + fib(n - 2);
	}
}

我们可以把这个递归的图给画出来

右边的肯定是要比左边递归的深度要小的,但是我们只用算大概的执行次数就行了,我们假设这个三角形是完整的,他的执行次数总数和就是 ( 1+2+4+……+2^n-2),最终结果的最高项肯定是2^n,所以这个算法的时间复杂度就是O(N)

int fib(int n)
{
	if (n == 1 || n == 2)
	{
		return 1;
	}
	int a = 1;
	int b = 1;
	int ret = 1;
	while (n>2)
	{
		ret = a + b; 
		a = b;
		b = ret;
		n--;
	}
	return ret;
}

这个算法的时间复杂度就是O(N)

我们还可以知道一些常用的算法的时间复杂度,比如冒泡排序的时间复杂度就是O(N^2),二分查找的时间复杂度就是logN,注意,我们在时间复杂度中的log都是默认以2为底的。

3.空间复杂度

时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需要的额外空间。 空间复杂度也是一个函数表达式,是对一个算法在运行过程中临时(额外)占用存储空间的大小。但是我们关注的也不是具体的内存的大小,还是因为硬件的原因,比如同一段代码,一个int类型的变量,在有的机器上他只占两个字节,而在有的机器上占四个字节,所以这个所占空间的具体的大小也是没有意义的。空间复杂度算的是变量的个数或者函数调用建立栈帧的次数或者层数(递归)。

就比如我们递归求斐波那契数的函数

我们可以将上面的每一个方块看成一个函数栈帧,但是我们要记住一点,我们调用fib(n-1)+fib(n-2)时,不是同时为这两个函数创建栈帧,而是会在fib(n-1)返回后再去调用fib(n-2),所以计算这个递归的空间复杂度看的不是调用的次数,而是递归的深度,同时,因为每次创建栈帧时栈帧的空间就已经是固定的了,也就是一个常数,在大O的渐进表示法中,加法的常数和系数的常数都是会删掉的,所以这个算法的空间复杂度就是O(N)。

在之前我们学完函数栈帧的时候就能发现,一个变量生命周期结束后,它的空间就还给了操作系统,如果我们在后面创建变量时,是有可能会重复利用这块空间的。

要记住,空间是可以重复利用的,不累积。而是就是一去不复返的,是累积的。在写算法的时候,我们尤其要注意算法的时间复杂度,必要时我们要采取以空间换时间的策略。

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

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

相关文章

12种常见的软件架构风格

什么是软件架构&#xff1f; 软件架构是定义软件系统的高级结构和组织的过程。它涉及识别和选择正确的组件&#xff0c;决定它们之间如何交互&#xff0c;以及确定它们应该如何组织以实现特定的目标。软件架构的目标是创建一个可维护、可扩展和安全的系统&#xff0c;能够满足…

车载电子电器架构 —— 软件下载

车载电子电器架构 —— 软件下载 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无…

【Qt】:常用控件(三:按钮类)

常用控件&#xff08;三&#xff09; 一.Push Button二.Radio Buttion三.Check Box 一.Push Button 使⽤ QPushButton 表⽰⼀个按钮.这也是当前我们最熟悉的⼀个控件了.QPushButton继承⾃QAbstractButton .这个类是⼀个抽象类.是其他按钮的⽗类. QAbstractButton 中,和 QPushBu…

基于java+SpringBoot+Vue的网上订餐系统设计与实现

基于javaSpringBootVue的网上订餐系统设计与实现 开发语言: Java 数据库: MySQL技术: Spring Boot JSP工具: IDEA/Eclipse、Navicat、Maven 系统展示 前台展示 菜品浏览与选择&#xff1a;用户可以浏览不同的菜品分类&#xff0c;并选择心仪的菜品。 订单创建与管理&…

做抖店的新手朋友!别再盲目跟风个人店了!开通完根本做不起来!

哈喽~我是电商月月 想做抖音小店的朋友们一定要分清个人店和个体店的区别 个人店铺的限制真的太多了&#xff01;真的不好做&#xff01; 一&#xff0e;首先我们要知道两种的区别 个人店不需要营业执照&#xff0c;身份证就能开启 个体店则需要办理营业执照【营业执照的办…

设计模式——建造者模式03

工厂模式注重直接生产一个对象&#xff0c;而建造者模式 注重一个复杂对象是如何组成的&#xff08;过程&#xff09;&#xff0c;在生产每个组件时&#xff0c;满足单一原则&#xff0c;实现了业务拆分。 设计模式&#xff0c;一定要敲代码理解 组件抽象 public interface …

算法设计与分析实验报告c++实现(排序算法、三壶谜题、交替放置的碟子、带锁的门)

一、实验目的 1&#xff0e;加深学生对分治法算法设计方法的基本思想、基本步骤、基本方法的理解与掌握&#xff1b; 2&#xff0e;提高学生利用课堂所学知识解决实际问题的能力&#xff1b; 3&#xff0e;提高学生综合应用所学知识解决实际问题的能力。 二、实验任务 1、 编…

JDI LCD 驱动时序介绍

1. 引言 绝大多数 STM32 MCU 都可应用于图形界面&#xff0c;而且很多系列还内置图形硬件 LTDC&#xff0c;支持驱动 RGB 接口的 LCD。但是存在少数类型的 LCD&#xff0c;如 JDI 屏&#xff0c;除了 STM32L4P5 支持外&#xff0c;其它 MCU 只能根据屏的接口时序要求&#xff…

DNS和HTTP

DNS应用层协议 域名解析系统 使用IP地址&#xff0c;来描述设备在网络上的位置 IP地址并不适合来进行传播网站&#xff0c;就采用了域名的方式来解决网站传播的问题。如www.baidu.com这样类似的就很容易让人记住。其域名就直接代表了这个网站。而且有一套自动的系统会将域名解…

LeetCode 2192.有向无环图中一个节点的所有祖先:拓扑排序

【LetMeFly】2192.有向无环图中一个节点的所有祖先&#xff1a;拓扑排序 力扣题目链接&#xff1a;https://leetcode.cn/problems/all-ancestors-of-a-node-in-a-directed-acyclic-graph/ 给你一个正整数 n &#xff0c;它表示一个 有向无环图 中节点的数目&#xff0c;节点编…

AFCI 应用笔记二之数据采集

1. 简介 基于监督学习的神经网络算法需要大量数据作为输入&#xff0c;模型完全由数据驱动&#xff0c;其数据质量是算法有效的必要条件&#xff0c;所以如何高效的采集到数据&#xff0c;以及正确的标注或分析是极其重要的&#xff0c;如果第一步有问题&#xff0c;后续的所有…

如何删除 iPhone 上的 iCloud 激活锁

Apple 在 iPhone 上通过不同的安全屏障来保护您的数据。 iCloud 激活锁可阻止外部人员访问您的手机。您可以通过打开“查找我的 iPhone”功能来激活此锁。 使用安全协议似乎是无害的&#xff0c;直到你到达门的另一边。如果您购买了带有激活锁的二手 iPhone 或忘记了 iCloud 凭…

eBay买家号注册下单容易死号?是什么原因导致?

随着电子商务的迅猛发展&#xff0c;跨境电商平台eBay日益成为众多消费者和商家的首选。然而&#xff0c;自去年下半年以来&#xff0c;eBay推出的新规则给买家号的注册带来了前所未有的挑战。许多新用户反映&#xff0c;在注册eBay买家号后&#xff0c;往往遭遇刚注册就被冻结…

哈希表2s总结

3.哈希表 哈希表非常常用&#xff0c;字典一般会用来保存处理过后的输入输出信息&#xff0c;集合也可以用来去重&#xff0c;这部分是重点&#xff0c;但是还是那句话&#xff0c;这种题目是不会或者说很少考原题的&#xff0c;主要还是学习知识&#xff0c;所以题目看一下答…

JS详解-手写Promise!!!

前言&#xff1a; 针对js的深入理解&#xff0c;作者学习并撰写以下文章&#xff0c;由于理解认知有限难免存在偏差&#xff0c;请大家指正&#xff01;所有定义来自mdn。 Promise介绍&#xff1a; 对象表示异步操作最终的完成&#xff08;或失败&#xff09;以及其结果值. 描…

基于SpringBoot+Vue光影视频平台(源码+部署说明+演示视频+源码介绍)

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。&#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通…

ChernoCPP 2

视频链接&#xff1a;【62】【Cherno C】【中字】C的线程_哔哩哔哩_bilibili 参考文章&#xff1a;TheChernoCppTutorial_the cherno-CSDN博客 Cherno的C教学视频笔记&#xff08;已完结&#xff09; - 知乎 (zhihu.com) C 的线程 #include<iostream> #include<th…

SV学习笔记(六)

覆盖率类型 写在前面 覆盖率是 衡量设计验证完备性 的一个通用词。随着测试逐步覆盖各种合理的场景&#xff0c;仿真过程会慢慢勾画出你的设计情况。覆盖率工具会 在仿真过程中收集信息 &#xff0c;然后进行后续处理并且得到覆盖率报告。通过这个报告找出覆盖之外的盲区&…

设计模式——原型模式05

原型模式核心复制&#xff0c;每次new出来的对象完全不一样&#xff0c;实现对象之间的隔离。 学习前最好先掌握jAVA值传递和深浅拷贝 设计模式&#xff0c;一定要敲代码理解 浅拷贝 克隆出对象&#xff0c;其中两者的引用类型属性是同一个对象。 对象信息 /*** author ggb…

C++:逻辑运算符-非与或(19)

!非!a如果a为假&#xff0c;那么当前他就是真&#xff0c;如果a是真&#xff0c;那么他直接就是假&&与a&&ba与b都为真&#xff0c;那么就是真&#xff0c;如果两个里面有一个为假那么就是假||或a||ba或b有一个为真&#xff0c;那么就是真 非&#xff08;!&…