Java时间复杂度和空间复杂度(详解)

目录

1.复杂度分析

2.时间复杂度

大O的渐进表示法

3.空间复杂度


1.复杂度分析

当我们设计一个算法时,怎样衡量其好坏?

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

2.时间复杂度

一个算法执行所需要的时间,我们可以将代码跑一遍得到具体的时间,但是如果每一个算法都测试一遍的话,十分耗费时间和精力,而且,其测试的结果高度依赖于测试环境,测试环境中的硬件不同会影响测试结果,测试数据的规模也会影响测试结果。

如果我们假设每行代码执行的时间都相同,那么此时影响时间的因素为语句的执行次数,即时间与其语句的执行次数成正比例

时间复杂度:算法中的基本操作的执行次数

public static int factorial(int N){int ret = 1;for (int i = 2; i <= N; i++) {ret *= i;}return ret;}

上述代码用来求n的阶乘,其中,在for前的代码每行执行了一次,在for循环(i++)及其中的代码(ret *= i)每行执行了N-1次,那么该代码总执行了(1+2*(N-1))次,即(2*N-1)次,代码具体执行了多少次,与传入数据n相关。

当 N = 100 时,代码执行 199 次

当 N = 1000时,代码执行 1999次

当 N = 10000时,代码执行 19999次

……

N越大,常数 -1,系数2对执行次数的影响越小。

因此,我们在计算时间复杂度时,并不需要计算精确的执行次数,只需要计算出其大概执行的次数,我们用大O的渐进表示法来表示

大O的渐进表示法

大O符号(Big O notation):用于描述函数渐进行为的数学符号

推导大O阶方法:

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

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

3.如果最高阶项存在且不是1,则去除与这个项目相乘的常数

例如,上述求阶乘的代码中,其执行次数为 2*N-1,用大O的渐进表示法,去掉对结果影响不大的项 -1,最高阶项去除与其相乘的常数,即为O(N)

在算法中,存在不同的执行情况,

例如在长度为N的数组中查找数据x时,可能执行一次就找到,也可能执行n次也找不到

我们将其分为最好、平均和最坏情况

最好情况:任意输入规模的最小运行次数

平均情况:任意输入规模的期望运行次数

最坏情况:任意输入规模的最大运行次数

而我们一般关注的是算法的最坏运行情况

我们通过一些例子来进一步熟悉大O的渐进表示法:

由于我们需要去掉对结果影响不大的项,因此我们可以不再分析对结果影响较小的语句。

例1:

public static int add(int a, int b){int ret = a+b;return ret;}

上述代码一共执行两次,用常数1取代其中的常数,即为 O(1)

例2:

 int fun(int N,int M){int count = 0;for (int i = 0; i < N; i++) {count++;}for (int i = 0; i < M; i++) {count++;}return count;}

上述代码一共有两个for循环,其中对执行次数影响最大(即执行次数最多)的语句为count++,共共执行了 N+M 次,

当 N 远大于 M时,时间复杂度为 O(N)

当 M 远大于 N时,时间复杂度为 O(M)

当 M 与 N 差不多大时,时间复杂度为 O(M+N)

由于没有说明N与M的大小关系,时间复杂度为 O(N+M)

例3:

    void fun(int N){int count = 0;for (int i = 0; i < N; i++) {for (int j = 0; j < i; j++) {count += j;}}}

 上述代码中有一个嵌套循环,其中对执行次数影响最大的语句为 count += j,我们对其进行分析

当 i = 0 时,语句执行 0 次,

当 i = 1 时,语句执行 1 次,

当 i = 2 时,语句执行 2 次,

……

当 i = N-1时,语句执行 N-1次

则总执行次数为 0 + 1 + 2 + …… + N-1,利用等差数列求和公式,可得结果为\frac{(N-1)*N}{2},最高阶项为\frac{^{N{_{}}^{2}}}{2},去掉系数,时间复杂度为 O(N^2)

例4:

void fun(int M){int count = 0;for (int i = 0; i < 10; i++) {count++;}}

 时间复杂度为O(1)

注意!count++ 语句一共执行了10次,与M没有关系

例5:

  public static int binarySearch(int[] arr, int x){if(arr.length == 0){return -1;}int left = 0;int right = arr.length-1;while(left <= right){int mid = left + ((right-left)>>1);if(arr[mid] == x){return mid;}else if(arr[mid] > x){right = mid;}else{left = mid+1;}}return -1;}

上述代码为二分查找,考虑最坏的情况,即查找不到:

我们先分析二分查找是如何查找数据的:

二分查找的前提是被查找的数组arr有序,通过确定中间位置mid,将数组分为两个部分,若被查找值x < arr[mid],则排除右边部分值,在左边继续进行二分查找;若x > arr[mid],则排除左边部分值,在右边继续进行二分查找;若 x = arr[mid],则找到被查找值,返回即可。

过程如下图所示:

由于一次二分查找会排除数组一半的元素,即

N/2

N/4

N/8

……

1 当结果为1时循环结束

因此 1*2*2*……*2 = N,即 2^x = N,则执行次数x = {log_{2}}^{}N

时间复杂度为O(log_{2}^{}N)

例6:

    long factorial(int N){return N < 2? N: factorial(N-1)*N;}

 上述递归的结束条件为 N < 2,当N >= 2时,会一直递归下去:

N

N-1

N-2

……

2

1 此时递归结束

递归的次数为N,因此时间复杂度为O(N)

例7:

    int fibonacci(int N){return N < 2? N: fibonacci(N-1)+ fibonacci(N-2);}

斐波那契递归,可将其看成一个二叉树,将其递归时开辟的栈帧看作一个节点,每一个节点就是一次函数调用,则递归的时间复杂度为二叉树结点个数,具体递归过程为:

 

其中最后一层可能不满,由于计算时间复杂度只需要计算出其大概执行的次数,最后一层的空缺对计算的影响可以忽略不计

则递归的次数为Fib(N) = 2^0 + 2^1 + ……+ 2^(N-1) 

 利用等比数列求和公式,可得2^n - 1,则时间复杂度为O(2^N)

3.空间复杂度

空间复杂度是对一共算法在运行过程中临时占用存储空间大小的量度。空间复杂度计算的是变量的个数,其计算规则基本与时间复杂度类似,也使用大O的渐进表示法

例1:

    void fun(int N){int count = 0;for (int i = 0; i < N; i++) {for (int j = 0; j < i; j++) {count += j;}}}

 其中开辟了常数个额外的变量(count、i、j),因此空间复杂度为O(1)

例2:

    int[] fun(int N){int[] arr = new int[N];for (int i = 0; i < N; i++) {arr[i] = i;}return arr;}

 开辟了一共大小为N的整形数组和常数个额外的变量,因此空间复杂度为O(N)

例3:

    long factorial(int N){return N < 2? N: factorial(N-1)*N;}

上述代码递归调用了N次,开辟了N个栈帧,每个栈帧使用了常数个空间,因此空间复杂度为O(N)

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

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

相关文章

java复习-线程的同步和死锁

线程的同步和死锁 同步问题引出 当多个线程访问同一资源时&#xff0c;会出现不同步问题。比如当票贩子A&#xff08;线程A&#xff09;已经通过了“判断”&#xff0c;但由于网络延迟&#xff0c;暂未修改票数的间隔时间内&#xff0c;票贩子B&#xff08;线程B&#xff09;…

SpringBoot-线程池ThreadPoolExecutor异步处理(包含拆分集合工具类)

ThreadPoolExecutor VS ThreadPoolTaskExecutor ThreadPoolTaskExecutor是对ThreadPoolExecutor进行了封装处理。 配置文件application.yml # 异步线程配置 自定义使用参数 async:executor:thread:core_pool_size: 10max_pool_size: 100 # 配置最大线程数queue_capacity: …

【css面试题】 实现一个盒子的水平竖直居中对齐效果

面试题里有时还会强调 子盒子宽高是否已知&#xff0c;要注意一下 尝试一&#xff1a;给父盒子设置padding 或者子盒子设置margin <style>.father{width: 300px;height: 200px;overflow: hidden; /* 放坑爹现象&#xff0c;不信你删了试试 */background-color: #db7b7b…

61、SpringBoot -----跨域资源的设置----局部设置和全局设置

★ 跨域资源共享的意义 ▲ 在前后端分离的开发架构中&#xff0c;前端应用和后端应用往往是彻底隔离的&#xff0c;二者不在同一个应用服务器内、甚至不再同一台物理节点上。 因此前端应用和后端应用就不在同一个域里。▲ 在这种架构下&#xff0c;前端应用可能采用前端框架&a…

【驱动开发】实现三盏灯的控制,编写应用程序测试

head.h #ifndef __HEAD_H__ #define __HEAD_H__//LED1:PE10 //LED2:PF10 //LED3:PE8#define LED_RCC 0X50000A28 //使能GPIO#define LED_MODER 0X50006000 //设置输出模式 #define LED_ODR 0X50006014 //设置输出高低电平#define LED2_MODER 0X50007000 …

JVM调优的GC日志观察解读

如果各项参数设置合理&#xff0c;系统没有超时日志出现&#xff0c;GC 频率不高&#xff0c;GC 耗时不高&#xff0c;那么没有必要进行 GC 优化 如果 GC 时间超过 1-3 秒&#xff0c;或者频繁 GC&#xff0c;则必须优化。 一、参数解读 Jvm 调优典型参数设置; -Xms: 堆内存的…

VMware vCenter 从6.7跨版本升级至7.0U3N

本文尝试使用 vCenter Server Appliance 管理界面 (VAMI) 进行对vCenter Server Appliance7应用进行小版本升级&#xff0c;从6.7.0.47000升级到7.0.3.01600&#xff08;7.0U3N&#xff09;。 一、升级前的准备工作 1、检查当前运行环境&#xff08;当前为6.7.0.47000&#x…

【办公自动化】用Python批量从上市公司年报中获取主要业务信息

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

软件测试行业已经卷到什么程度了?

近几个月经常听到IT行业的人员吐槽找工作难的事情&#xff0c;特别是找软件测试工作相比前几年难了很多&#xff0c;以前只要简历一挂网上&#xff0c;每天会接到好多个面试邀请电话&#xff0c;甚至两三天或者一周内就能把工作找好&#xff0c;而现在把简历投了个遍&#xff0…

在Linux上利用宝塔面板搭建网站,并通过内网穿透方便地实现公网访问

文章目录 前言1. 环境安装2. 安装cpolar内网穿透3. 内网穿透4. 固定http地址5. 配置二级子域名6. 创建一个测试页面 前言 宝塔面板作为简单好用的服务器运维管理面板&#xff0c;它支持Linux/Windows系统&#xff0c;我们可用它来一键配置LAMP/LNMP环境、网站、数据库、FTP等&…

IDEA报错:No valid Maven installation found

当我想要用maven进行clean的时候&#xff0c;发现报了这个错误&#xff0c;idea的event logs记录为 网上又说可能是因为你的maven环境没有配置好&#xff0c;我对我的maven进行了检查&#xff0c;发现是没有问题的&#xff0c;在这里提醒大家&#xff0c;如果你以前的项目maven…

计算机竞赛 机器视觉opencv答题卡识别系统

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 答题卡识别系统 - opencv python 图像识别 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满分5分…

ChatGPT新增超强插件:文本直接生成视频、海报,支持自定义修改!

全球著名在线设计平台Canva&#xff0c;在ChatGPT Plus&#xff08;GPT-4&#xff09;上推出了插件功能&#xff0c;用户通过文本提示&#xff0c;几秒钟就能生成演示文稿、PPT插图、电子书封面、宴会邀请函等各种精美设计海报&#xff0c;同时支持生成视频。 该插件最强大的功…

爬虫系统的核心:如何创建高质量的HTML文件?

在网页抓取或爬虫系统中&#xff0c;HTML文件的创建是一项重要的任务。HTML文件是网页的基础&#xff0c;包含了网页的所有内容和结构。在爬虫系统中&#xff0c;我们需要生成一个HTML文件&#xff0c;以便于保存和处理网页的内容。 在这种情况下&#xff0c;可以使用Java函数…

Zebec 生态 AMA 回顾:Nautilus 以及 $ZBC 的未来

在9月7日&#xff0c;Zebec创始人Sam做客社区&#xff0c;并进行了“Nautilus Chain以及$ZBC的未来”主题的AMA访谈。Sam在本次访谈中对Nautilus Chain生态的价值捕获、Zebec生态布局规划、可能会推出的Nautilus Chain治理通证NAUT进行了解读。本文将对本次AMA进行回顾与总结。…

城市内涝监测预警系统:有效降低内涝风险,保障城市安全

近日&#xff0c;受台风“海葵”的影响&#xff0c;福建广东多地遭遇了持续性强降雨的袭击&#xff0c;道路积水严重&#xff0c;“城市看海”模式再次开启&#xff0c;不少网友纷纷调侃房子已经升级为海景房。近年来受极端天气影响&#xff0c;城市内涝灾害越发凸显&#xff0…

0015Java程序设计-springboot美食网站

摘 要目 录**绪论**1.1背景及意义1.2 国内外研究概况1.3 研究的内容 开发环境 摘 要 随着移动应用技术的发展&#xff0c;越来越多的用户借助于移动手机、电脑完成生活中的事务&#xff0c;许多的传统行业也更加重视与互联网的结合。 本论文主要介绍基于java的美食网站&#…

Jmeter安装与测试

目录 一&#xff1a;JMeter简介&#xff1a; 二&#xff1a;JMeter安装与配置 三&#xff1a;JMeter主要原件 一&#xff1a;JMeter简介&#xff1a; JMeter&#xff0c;一个100&#xff05;的纯Java桌面应用&#xff0c;由Apache组织的开放源代码项目&#xff0c;它是功能 …

VoxWeekly|The Sandbox 生态周报|20230911

欢迎来到由 The Sandbox 发布的《VoxWeekly》。我们会在每周发布&#xff0c;对上一周 The Sandbox 生态系统所发生的事情进行总结。 如果你喜欢我们内容&#xff0c;欢迎与朋友和家人分享。请订阅我们的 Medium 、关注我们的 Twitter&#xff0c;并加入 Discord 社区&#xf…

gif动画如何快速生成?教你几步快速搞定gif制作

gif动画图片已经充斥着我们的日常生活&#xff0c;它的画面丰富生动&#xff0c;且易于传播和保存。平时工作时也能用到&#xff0c;特别是需要有操作演示的时候&#xff0c;就可以把演示的视频做成gif动图。通过使用【GIF中文网】这款gif动画制作&#xff08;https://www.gif.…