算法复杂度分析看这一篇就够了

2023年也慢慢的步入了年末,光阴易逝,前段时间在学习算法的时候谈到了复杂度,所以今天就来总结一下

算法的复杂度是衡量算法执行效率的度量标准。它描述了随着输入规模的增加,算法所需执行的基本操作的数量或运行时间的增长程度。一般来说,算法的复杂度可以分为时间复杂度和空间复杂度。

时间复杂度衡量的是执行算法所需的时间,通常以大O符号(O)来表示。例如,O(1)表示常数时间复杂度,即算法的执行时间与输入规模无关;O(n)表示线性时间复杂度,算法的执行时间与输入规模呈线性关系;O(n^2)表示平方时间复杂度,算法的执行时间与输入规模的平方成正比,等等。

空间复杂度衡量的是算法在执行过程中所需的额外空间,通常也使用大O符号进行表示。空间复杂度可以用于评估算法在内存消耗方面的效率。与时间复杂度类似,O(1)表示常数空间复杂度,O(n)表示线性空间复杂度,O(n^2)表示平方空间复杂度,等等。

总的来说,算法的复杂度帮助我们评估算法的效率和可扩展性,从而在设计和选择算法时做出更明智的决策。

学好算法需要具备那些点

学习算法需要具备以下几个品质:

  • 好奇心:对于算法和问题的好奇心是非常重要的。好奇心会驱使你主动去了解和探索各种不同类型的算法,以及它们在解决问题上的应用。

  • 坚持与耐心:学习算法是一个需要持续努力和坚持的过程。有时算法可能会很复杂或难以理解,但通过持之以恒的学习和实践,你将逐渐掌握它们。

  • 数学基础:虽然不是所有的算法都需要深厚的数学知识,但良好的数学基础可以帮助你更好地理解和分析算法的原理和表现。

  • 逻辑思维能力:算法与逻辑密切相关,因此具备良好的逻辑思维能力可以帮助你更好地理解和设计算法。

  • 编程能力:学习算法通常需要使用编程语言来实现和测试。因此,具备一定的编程能力,熟悉常见的编程语言和算法实现方式是必要的。

  • 分析和解决问题的能力:学习算法的目的是为了解决实际问题。具备良好的问题分析和解决能力可以帮助你选择适当的算法,并应用它们来解决实际问题。

  • 团队合作能力:在现实世界中,算法通常是由团队合作开发和优化的。具备良好的团队合作能力可以帮助你更好地与他人交流和协作,共同完成算法实现和优化的任务。

学习算法需要持续地学习、实践和思考,同时具备好奇心、耐心、数学基础、逻辑思维能力、编程能力、问题解决能力和团队合作能力。通过培养这些品质,你将能够更好地理解和应用不同类型的算法。

1.1 算法复杂度分析

1.1.1 概念
  1. 数据结构是指一组数据的存储结构
  2. 算法就是操作数据的方法

举个例子:

image-20220918101508113.png

比如,你要搬家,有一堆货物,这个时候你可以选择使用小桥车拉走货物,你可以选择小货车拉走货物。其实现在你选择哪辆车装载货物就相当于选择了哪种数据结构。

你选择小货车拉走货物,但是货物依然很多,你这个时候需要规整一下,难看怎么着更能节省空间,更能节省效率,这个动作就是算法了

清楚了这些概念之后,如果只是单独讲数据结构和算法是不合适的,它们两个是相辅相成的。

1.1.2 算法复杂度

复杂度也叫渐进复杂度,包括时间复杂度空间复杂度,用来分析算法执行效率与数据规模之间的增长关系,可以粗略地表示,越高阶复杂度的算法,执行效率越低。

复杂度描述的是算法执行时间或占用内存空间随数据规模的增长关系。

举例:

有200人需要从成都到北京,可以选择很多交通工具,每个交通工具的载客量和时间都不相同

  • 大型载人客车,50人每车,需要4辆车,时间大概为30小时
  • 普通火车,载客量超大,满足200人的需求,时间大概为20小时
  • 高铁,载客量超大,满足200人的需求,时间大概为9小时
  • 飞机,载客量适中,满足200人的需求,时间大概为3小时

算法的执行效率,粗略地讲,就是算法代码执行的时间,那如何在不直接运行代码的前提下粗略的计算执行时间呢?

分析以下代码

/**
  * 求1~n的累加和
  * @param n
  * @return
  */
public static int sum(int n){
    int sum = 0;
    for (int i = 1; i < n; ++i) {
        sum  = sum + i;
    }
    return sum;
}

假设每行代码执行时间都一样为:timer

此代码的执行时间为:(3n+3) timer

总结:所有代码的执行时间T(n)与代码的执行次数成正比

按照该思路我们接着看下面一段代码

public static int sum2(int n){
    int sum = 0;
    for (int i = 1; i < n; ++i) {
        for (int j = 1; j < n; ++j) {
            sum = sum + i * j;
        }
    }
    return sum;
}

同理,此代码的执行时间为: (3 n^2 + 3n + 3) * timer

因此有一个重要结论:代码的执行时间T(n)与总的执行次数相关 ,我们可以把这个规律总结成一个公式。

T(n) = O(f(n))

T(n)表示代码的执行时间,n表示数据规模的大小,f(n)表示了代码执行的总次数,它是一个公式因此用f(n)表示,O表示了代码执行时间与f(n)成正比

1.1.3 大O复杂度表示法

大 O 时间复杂度实际上并不具体表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势,所以,也叫作渐进时间复杂度,简称时间复杂度。

当n很大时,公式中的低阶,常量,系数三部分并不左右其增长趋势,因此可以忽略,我们只需要记录一个最大的量级就可以了,因此如果用大O表示刚刚的时间复杂度可以记录为

第一个例子中的T(n)=O(3n+3) -----> T(n)=O(n)

第二个例子中的T(n)=O(3 n^2 + 3n + 3) -------> T(n)=O(n^2)

常见的复杂度

描述表示形式
常数O(1)
线性O(n)
对数O(log n)
线性对数O(n * log n)
平方O(n ^2)
立方O(n ^3)
k次方O(n ^k)
指数O(2 ^n)
阶乘O(n !)
1.1.4 O(1)
public int test01(int n){
    int i=0;
    int j = 1;
    return i+j;
}

代码只有三行,它的复杂度也是O(1),而不是O(3)

再看如下代码:

public void test02(int n){
    int i=0;
    int sum=0;
    for(;i<100;i++){
        sum = sum+i;
    }
    System.out.println(sum);
}

整个代码中因为循环次数是固定的就是100次,这样的代码复杂度我们认为也是O(1)

一句话总结:只要代码的执行时间不随着n的增大而增大,这样的代码复杂度都是O(1)

1.1.5 O(n)

这个大家已经不陌生了,就是刚才上面的两个例子

/**
 * 求1~n的累加和
 * @param n
 * @return
 */
public int sum(int n) {
    int sum = 0;
    for ( int i = 1; i <= n; i++) {
        sum = sum + i;
    }
    return sum;
}

一层for循环的时间复杂度是 O(n)

public static int sum2(int n){
    int sum = 0;
    for (int i = 1; i < n; ++i) {
        for (int j = 1; j < n; ++j) {
            sum = sum + i * j;
        }
    }
    return sum;
}

两层for循环的时间复杂度是 O(n^2)

1.1.6 O(log n)

对数复杂度非常的常见,但相对比较难以分析,代码:

public void test04(int n){
    int i=1;
    while(i<=n){
        i = i * 2;
    }
}

分析这个代码的复杂度,我们必须要再强调一个前提:复杂度分析就是要弄清楚代码的执行次数和数据规模n之间的关系

以上代码最关键的一行是:i = i * 2,这行代码可以决定这个while循环执行代码的行数,i的值是可以无限接近n的值的。如果i 一旦大于等于了n则循环条件就不满足了。也就说达到了最大的行数。我们可以分析一下i这个值变化的过程

分析过程如下:

image-20220918103139078.png

由此可知,代码的时间复杂度表示为O(log n)

1.1.7 O(n * log n)

分析完O( log n ),那O( n * log n )就很容易理解了,比如下列代码:

public void test05(int n){
    int i=0;
    for(;i<=n;i++){
        test04(n);
    }
}

public void test04(int n){
    int i=1;
    while(i<=n){
        i = i * 2;
    }
}
1.1.8 空间复杂度

空间复杂度全称是渐进空间复杂度,表示算法占用的额外存储空间数据规模之间的增长关系

看下面代码

public void test(int n){
    int i=0;
    int sum=0;
    for(;i<n;i++){
        sum = sum+i;
    }
    System.out.println(sum);
}

代码执行并不需要占用额外的存储空间,只需要常量级的内存空间大小,因此空间复杂度是O(1)

再来看一个其他例子:

void print(int n) {
    int i = 0;
    int[] a = new int[n];
    for (i; i <n; ++i) {
        a[i] = i * i;
    }
    for (i = n-1; i >= 0; --i) {
        System.out.println(a[i]);
    }
}

传入一个变量n,决定申请多少的int数组空间内存,此段代码的空间复杂度为O(n)

我们常见的空间复杂度就是O(1),O(n),O(n ^2),其他像对数阶的复杂度几乎用不到,因此空间复杂度比时间复杂度分析要简单的多。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JSP的学习

1.JSP概念: Java服务端页面;一种动态的网页技术,既可以定义HTML,JS,CSS等静态内容,也可以定义Java代码的动态内容;JSPHTMLJava;JSP的作用:简化开发,避免了在Servlet中直接输出HTML标签; 2.JSP快速入门 3.JSP原理 概念&#xff1a;Java Server Pages&#xff0c;Java服务端页…

C# CefSharp 输入内容,点击按钮,并且滑动。

前言 帮别人敲了个Demo,抱试一试心态&#xff0c;居然成功了&#xff0c;可以用。给小伙伴们看看效果。 遇到问题 1&#xff0c;input输入value失败&#xff0c;里面要套了个事件&#xff0c;再变换输入value。后来用浏览器开发工具&#xff0c;研究js代码&#xff0c;太难了&a…

UG制图-全剖和阶梯剖

当机件的内部形状较复杂时&#xff0c;视图上将出现许多虚线&#xff0c;不便于看图和标注尺寸 解决方法就是使用剖视图 剖视图的形成&#xff1a;假想用一个剖切面将机件剖开&#xff0c;移去剖切面和观察者之间的部分&#xff0c;将其余部分向投影面投射&#xff0c;并在剖切…

【数据结构】 链栈的基本操作 (C语言版)

目录 一、链栈 1、链栈的定义&#xff1a; 2、链栈的优缺点&#xff1a; 二、链栈的基本操作算法&#xff08;C语言&#xff09; 1、宏定义 2、创建结构体 3、链栈的初始化 4、链栈的进栈 5、链栈的出栈 6、获取栈顶元素 7、栈的遍历输出 8、链栈的判空 9、求链…

Windows内网渗透篇-后门持久化姿势总结

简介 拿下服务器之后,应该怎么做到持久化控制呢?下面总结了内网渗透中常见的持久化姿势,如:映像劫持,定时任务,登录脚本等常见持久化操作,希望对大家工作或者学习有一定的帮助. 隐藏文件 创建系统隐藏文件attrib +s +a +r +h filename attrib +s +h filename 利用NTFS ADS…

JeecgBoot集成TiDB,打造高效可靠的数据存储解决方案

TiDB简介 TiDB是PingCAP公司自主设计、研发的开源分布式关系型数据库&#xff0c;同时支持在线事务处理与在线分析处理 (Hybrid Transactional and Analytical Processing, HTAP) 的融合型分布式数据库产品&#xff0c;具备水平扩容或者缩容、金融级高可用、实时 HTAP、云原生…

Vue3组件库开发 之Button(2) 未完待续

Vue3组件库开发 之Button(1) 中新建项目&#xff0c;但未安装成功ESLINT 安装ESLINT npm install eslint vite-plugin-eslint --save-dev 安装eslint后&#xff0c;组件文件出现错误提示 添加第三方macros &#xff0c;虽然不是官网但很多开发者都是vue3开发人员 安装macros…

用通俗易懂的方式讲解:使用 MongoDB 和 Langchain 构建生成型AI聊天机器人

想象一下&#xff1a;你收到了你梦寐以求的礼物&#xff1a;一台非凡的时光机&#xff0c;可以将你带到任何地方、任何时候。 你只有10分钟让它运行&#xff0c;否则它将消失。你拥有一份2000页的PDF&#xff0c;详细介绍了关于这台时光机的一切&#xff1a;它的历史、创造者、…

Midjourney 提示词入门 | 提示词格式 特点如何写好自己的提示词?进阶技巧

文章目录 1 Prompt格式2 文本提示词的基本要求3 好的文本提示词的特点 上一节我们初步了解了Midjourney的使用 那么在使用过程中最重要的是通过Prompt告知Midjourney怎么画 因而高效写Prompt非常重要~ 先来了解一下Prompt基本格式 1 Prompt格式 /imagine Text_prompt如下图…

CSS文本外观属性内容(知识点1)

知识引入 使用HTML可以对文本外观进行简单的控制&#xff0c;但是效果并不理想&#xff0c;为此CSS提供了一系列的文本外观样式属性&#xff0c;具体如下。 color:文本颜色 color属性用于定义文本的颜色&#xff0c;其取值方式有以下三种。 &#xff08;1&#xff09;预定义…

11.什么档次的原型模式和我写的一样

在《生化危机》系列电影中&#xff0c;克隆人是个频频出现的话题。保护伞公司为了需求复制出另一个战力相当的战士Alice&#xff0c;不惜克隆成百上千个Alice&#xff0c;然而直到最后&#xff0c;非但没有真正克隆出另一个完美的Alice&#xff0c;就连Alice自己也被证实是保护…

conda+sh----Windows在conda环境中运行.sh文件

在玩项目的时候发现需要运行.sh文件&#xff0c;但是查询后发现这是linux的命令&#xff0c;cmd直接运行就是sh不是内外部命令,总结了一下使用方法 1、下载安装git 下载git工具下载连接 记住安装路径 2、修改系统变量 右键此电脑—属性—高级系统设置—环境变量&#xff0…

MySQL也开始支持JavaScript了

2023 年 12 月 16 日&#xff0c;Oracle 公司在一篇名为 《Introducing JavaScript support in MySQL》的文章中宣布 MySQL 数据库服务器将开始支持 JavaScript 语言。 这个举措标志着继PostgreSQL之后&#xff0c; MySQL 也支持使用 JavaScript 编写函数和存储过程了。作为最…

JAVA:OFD Reader Writer 开源库技术解析

1、简述 OFD Reader & Writer 是一个由开源社区推动的 OFD 文件处理库&#xff0c;它旨在提供对 OFD 格式文件的读取和写入功能。这一开源项目为开发者提供了强大而灵活的工具&#xff0c;使得在应用程序中处理和生成 OFD 文件变得更加容易和高效 开源地址&#xff1a;htt…

中文数据让LLM变笨?

我这里先贴一下论文的原链接&#xff1a; https://arxiv.org/abs/2401.10286 然后贴一下我翻译标注的下载链接&#xff1a;https://gitee.com/chatpaper/arXiv_top_chinese/blob/master/0801_top/%E4%B8%AD%E6%96%87%E4%BC%9A%E8%AE%A9LLM%E5%8F%98%E7%AC%A8%EF%BC%9F.pdf 先…

Nginx查看并发连接数

前言 需要依赖于nginx的http_stub_status_module模块http://nginx.org/en/docs/ 查看是否已经安装此模块 windows: linux: 添加/status 在server段内&#xff0c;添加如下配置&#xff1a; server {listen 80;server_name localhost;root "D:/WWW/local…

huggingface学习|云服务器部署Grounded-Segment-Anything:bug总会一个一个一个一个又一个的解决的

文章目录 一、环境部署&#xff08;一&#xff09;模型下载&#xff08;二&#xff09;环境配置&#xff08;三&#xff09;库的安装 二、运行&#xff08;一&#xff09; 运行grounding_dino_demo.py文件&#xff08;二&#xff09;运行grounded_sam_demo.py文件&#xff08;三…

机器学习期末复习总结笔记(李航统计学习方法)

文章目录 模型复杂度高---过拟合分类与回归有监督、无监督、半监督正则化生成模型和判别模型感知机KNN朴素贝叶斯决策树SVMAdaboost聚类风险PCA深度学习范数计算梯度下降与随机梯度下降SGD线性回归逻辑回归最大熵模型适用性讨论 模型复杂度高—过拟合 是什么&#xff1a;当模型…

OSPF基础华为ICT网络赛道

6.1.OSPF协议概述 由协议之中OSPF(Open Shortest Path First,开放式最短路径优先)协议是使用场 景非常广泛的动态路由协议之一。 OSPF在RFC2328中定义&#xff0c;是一种基于链路状态算法的路由协议。 静态路由是由工程师手动配置和维护的路由条目&#xff0c;命令行简单明确…

用Go plan9汇编实现斐波那契数列计算

斐波那契数列是一个满足递推关系的数列&#xff0c;如&#xff1a;1 1 2 3 5 8 ... 其前两项为1&#xff0c;第3项开始&#xff0c;每一项都是其前两项之和。 用Go实现一个简单的斐波那契计算逻辑 func fib(n int) int {if n 1 || n 2 {return 1}return fib(n-1) fib(n-2) …