02、Java 数据结构:时间复杂度与空间复杂度

news2024/10/5 22:24:01

时间复杂度与空间复杂度

  • 1 场景理解
    • 1.1 场景1
    • 1.2 场景2
    • 1.3 场景3
    • 1.4 场景4
    • 1.5 代码实现
  • 2 时间复杂度
    • 2.1 渐进时间复杂度
    • 2.2 从基本操作执行次数推导出时间复杂度
    • 2.3 两种方法来计算
    • 2.4 四个场景的时间复杂度分析
    • 2.5 大 O 表达式的优劣
  • 3 空间复杂度
  • 4 时间复杂度和空间按复杂度关系
    • 4.1 关系
    • 4.2 例子
    • 4.3 程序中的应用

1 场景理解

1.1 场景1

给大黄一条长10寸的面包,大黄每3天吃掉1寸,那么吃掉整个面包需要几天?

  • 答案自然是 3 X 10 = 30天。
  • 如果面包的长度是 N 寸呢?
  • 此时吃掉整个面包,需要 3 X n = 3n 天。
  • 如果用一个函数来表达这个相对时间,可以记作 T(n) = 3n。

1.2 场景2

给大黄一条长16寸的面包,大黄每5天吃掉面包剩余长度的一半,第一次吃掉8寸,第二次吃掉4寸,第三次吃掉2寸…那么大黄把面包吃得只剩下1寸,需要多少天呢?

  • 这个问题翻译一下,就是数字16不断地除以2,除几次以后的结果等于1?这里要涉及到数学当中的对数,以2位底,16的对数,可以简写为log16。因此,把面包吃得只剩下1寸,需要 5 X log16 = 5 X 4 = 20 天。
  • 如果面包的长度是 N 寸呢?
  • 需要 5 X logn = 5logn 天,记作 T(n) = 5logn。

1.3 场景3

给大黄一条长10寸的面包和一个鸡腿,大黄每2天吃掉一个鸡腿。那么大黄吃掉整个鸡腿需要多少天呢?

  • 答案自然是2天。因为只说是吃掉鸡腿,和10寸的面包没有关系 。
  • 如果面包的长度是 N 寸呢?
  • 无论面包有多长,吃掉鸡腿的时间仍然是2天,记作 T(n) = 2。

1.4 场景4

给大黄一条长10寸的面包,大黄吃掉第一个一寸需要1天时间,吃掉第二个一寸需要2天时间,吃掉第三个一寸需要3天时间…每多吃一寸,所花的时间也多一天。那么大黄吃掉整个面包需要多少天呢?

  • 答案是从1累加到10的总和,也就是55天。
  • 如果面包的长度是 N 寸呢?
  • 此时吃掉整个面包,需要 1+2+3+…+ n-1 + n = (1+n)*n/2 = 0.5n^2 + 0.5n。
  • 记作 T(n) = 0.5n^2 + 0.5n。

1.5 代码实现

上面所讲的是吃东西所花费的相对时间,这一思想同样适用于对程序基本操作执行次数的统计。刚才的四个场景,分别对应了程序中最常见的四种执行方式

场景1: T(n) = 3n,执行次数是线性的

void eat1(int n){
    for(int i=0; i<n; i++){;
        System.out.println("等待一天");
        System.out.println("等待一天");
        System.out.println("吃一寸面包");
    }
}

场景2: T(n) = 5logn,执行次数是对数的

void eat2(int n){
   for(int i=1; i<n; i*=2){     
       System.out.println("等待一天");
       System.out.println("等待一天");
       System.out.println("等待一天");
       System.out.println("等待一天");
       System.out.println("吃一半面包");
   }
}

场景3: T(n) = 2,执行次数是常量的

void eat3(int n){
   System.out.println("等待一天");
   System.out.println("吃一个鸡腿");
}

场景4: T(n) = 0.5n^2 + 0.5n,执行次数是一个多项式

void eat4(int n){
   for(int i=0; i<n; i++){   
       for(int j=0; j<i; j++){
           System.out.println("等待一天");  
       }
       System.out.println("吃一寸面包");   
   }
}

2 时间复杂度

2.1 渐进时间复杂度

  • 有了基本操作执行次数的函数 T(n),是否就可以分析和比较一段代码的运行时间了呢?还是有一定的困难
  • 比如算法 A 的相对时间是T(n)= 100n,算法 B 的相对时间是 T(n)= 5n^2,这两个到底谁的运行时间更长一些?这就要看 n 的取值了。所以,这时候有了渐进时间复杂度(asymptotic time complectiy)的概念
  • 官方的定义如下:若存在函数 f(n),使得当 n 趋近于无穷大时,T(n) / f(n) 的极限值为不等于零的常数,则称 f(n) 是 T(n) 的同数量级函数。记作 T(n) = O(f(n)),称 O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。渐进时间复杂度用大写 O 来表示,所以也被称为大 O 表达式

2.2 从基本操作执行次数推导出时间复杂度

  • 如果程序的运行次数和要处理的量n的大小没有关系,用常数1表示;O(1)
  • 如果程序的运行次数和要处理的量n的大小有关系,只保留关系函数中的最高阶项; O(n^2)
  • 如果最高阶项存在,则省去最高阶项前面的系数。 O(n^2)

2.3 两种方法来计算

  • 事后统计:写出代码,计算时间,不推荐。
  • 事前分析:比较所有语句执行的次数总和,为了方便,仅比较它们的数量级就行
    在这里插入图片描述

有时候复杂度会受其他数据的影响,会有最坏时间复杂度、平均时间复杂度、最好时间复杂度,一般情况下,只考虑最坏时间复杂度和平均时间复杂度

对于复杂的算法,可以将其分为几个容易估算的部分,然后利用大 O 加法法则和乘法法则,计算算法的复杂度:

  • 加法法则取时间复杂度最大的一个
  • 乘法法则几个计算出来的最后时间复杂度相乘
    在这里插入图片描述

2.4 四个场景的时间复杂度分析

场景1:
T(n) = 3n
最高阶项为3n,省去系数3,转化的时间复杂度为:T(n) = O(n) 大 O 线性阶
在这里插入图片描述
场景2:
T(n) = 5logn
最高阶项为5logn,省去系数5,转化的时间复杂度为:T(n) = O(logn) 大 O 对数阶
在这里插入图片描述

场景3:
T(n) = 2
只有常数量级,转化的时间复杂度为:T(n) = O(1) 大 O 常数阶
在这里插入图片描述

场景4:
T(n) = 0.5n^2 + 0.5n
最高阶项为 0.5n^2,省去系数0.5,转化的时间复杂度为:T(n) = O(n^2) 大 O 平方阶
在这里插入图片描述

2.5 大 O 表达式的优劣

大O表达式算法的好坏
O(1)最好
O(logn)比较好
O(n)良好
O(n^2)不好
O(n^3)很不好
O(2^n)很很不好
O(n!)最不好

例子:

  • 算法A的相对时间规模是 T(n)= 100n*100,时间复杂度是 O(n)
  • 算法B的相对时间规模是 T(n)= 5n^2,时间复杂度是 O(n^2)
  • 随着输入规模 n 的增长,两种算法谁运行更快呢?
    在这里插入图片描述
    从表格中可以看出,当 n 的值很小的时候,算法 A 的运行用时要远大于算法 B;当 n 的值达到1000左右,算法 A 和算法 B 的运行时间已经接近;当 n 的值越来越大,达到十万、百万时,算法 A 的优势开始显现,算法 B 则越来越慢,差距越来越明显

3 空间复杂度

空间复杂度和时间复杂度很类似,当一个算法的空间复杂度为一个常量,即不随被处理数据量 n 的大小而改变时,可表示为 O(1);当一个算法的空间复杂度与以2为底的 n 的对数成正比时,可表示为 O(log2n);当一个算法的空间复杂度与 n 成线性比例关系时,可表示为O(n)…

4 时间复杂度和空间按复杂度关系

4.1 关系

程序的设计中要不就是时间换空间,要不就是用空间去换时间。并且时间和空间是可以进行相互转化的:

  • 对于执行的慢的程序,可以通过消耗内存(即构造新的数据结构)来进行优化
  • 消耗内存的程序,也可以多消耗时间来降低内存的消耗

4.2 例子

//时间换空间
int a = 5;
int b = 10;
a = a+b;//得到a值为15
b = a-b;//得到b值为5
a = a-b;//得到a值为10

//空间换时间
int c = 5;
int d = 10;
int e = c;//得到e为5
c= d;//得到c值为10
d= e;//得到d值为 

结论:

  • 第一个 a 和 b 互换值的算法:总共进行了3次加减运算和三次赋值运算,能够把 a 和 b 的值进行互换,没有开辟多余的内存空间
  • 第二个 c 和 d 互换的时候,多开辟了一个内存空间存储 e,但是这样只需要进行三次赋值运算就可以把 c 和 d 的值进行互换
  • 所以第一个算法空间效率高,时间效率低,第二个算法空间效率低,时间效率高

4.3 程序中的应用

在程序当中,请求分页,请求分段,都属于用时间去换空间。在项目当中使用各种缓存技术,都属于利用空间去换时间。

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

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

相关文章

《计算机网络》——第四章知识点

第四章思维导图如下&#xff1b; 网络层向上只提供灵活的、无连接的、尽最大努力交付的数据报服务&#xff0c;主要任务是把分组&#xff08;IP数据报)从通过路由选择与转发从源端传到目的端&#xff0c;为分组交换网上的不同主机提供通信服务。 互联网可以由多种异构网络互连…

基于Shell编程完成定时备份数据库,看这篇就够了

一. 前言 最近文哥班里有一个学员面试成功上岸&#xff0c;在公司开发时遇到了这么一个需求&#xff1a;领导要求他编写一个shell脚本&#xff0c;完成定时备份数据库的需求。由于他对linux以及shell编程不是很了解&#xff0c;这位学员感到束手无策&#xff0c;于是就求助文哥…

List的介绍

目录 1.什么是List 2.常见接口介绍 3.List 1.什么是List 在集合框架中&#xff0c;List是一个接口&#xff0c;继承自Collection。Collection也是一个接口&#xff0c;该接口规范了后续容器中常用的一些方法&#xff0c;具体如下所示 Iterable也是一个接口&#xff0c;表示实…

ArcGIS基础实验操作100例--实验11以线要素分割面要素(一)

本实验专栏来自于汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 基础编辑篇--实验11 以线要素分割面要素&#xff08;一&#xff09; 目录 一、实验背景 二、实验数据 …

今年十八,蓝桥速刷(Python-I)

前言 &#x1f340;作者简介&#xff1a;被吉师散养、喜欢前端、学过后端、练过CTF、玩过DOS、不喜欢java的不知名学生。 &#x1f341;个人主页&#xff1a;红中 &#x1f342;专栏地址&#xff1a;python专栏 抽根烟先 蓝桥杯是个啥 蓝桥杯&#xff0c;又称圈钱杯(不是 是由…

MySQL数据库调优

MySQL数据库调优一、MySQL架构设计1.1、引言1.2、MySQL Server层1.2.1、连接器&#xff08;Connector&#xff09;1.2.2、查询缓存 &#xff08;Query Cache&#xff09;1.2.3、分析器&#xff08;Analyzer&#xff09;1.2.4、优化器&#xff08;optimizer&#xff09;1.2.5、执…

Qt5操作Office及Word读写实例

欢迎小伙伴的点评✨✨&#xff0c;相互学习&#x1f680;&#x1f680;&#x1f680; 博主&#x1f9d1;&#x1f9d1; 本着开源的精神交流Qt开发的经验、将持续更新续章&#xff0c;为社区贡献博主自身的开源精神&#x1f469;‍&#x1f680; 文章目录前言一、Qt操作Office的…

云超融合数据中心 CloudFabric

大家好&#xff0c;我是技福的小咖老师。 随着云计算、大数据、人工智能等新一代信息技术的快速发展&#xff0c;数字技术已经渗透到我们日常生活的方方面面&#xff0c;同时也改变了所有行业。数据中心&#xff0c;将算力源源不断地输送给数字世界&#xff0c;逐渐成为云计算…

Flink学习28:水位线

1.前言 flink有3种时间&#xff0c;主要是事件时间和处理时间。 水位线主要解决&#xff0c;数据乱序到达或者延迟到达的问题 2.水位线原理 即只有当水位线&#xff0c;越过窗口的结束时间&#xff0c;才会触发窗口计算。 窗口计算需要同时满足两个条件&#xff1a; 1.水位线…

spring之IoC注解

文章目录前言一、回顾注解1、注解怎么定义2、注解怎么使用3、通过反射机制怎么读取注解二、Spring IoC注解式开发原理1、扫描程序2、通过反射机制解析注解3、实例化对象三、声明Bean的注解前言 注解的存在主要是为了简化XML的配置 一、回顾注解 1、注解怎么定义 定义一个注解…

c语言操作符(上)

前言 &#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏: &#x1f354;&#x1f35f;&#x1f32f; c语言初阶 &#x1f511;个人信条: &#x1f335;知行合一 &#x1f349;本篇简介:>: 讲解c语言中有关操作符的知识. 金句分享: 最慢的步伐…

Python读取sqlite3数据库中的数据

文章目录1. 简介1.1. 使用1.1.1. 创建1.1.2. 插入1.1.2.1. 插入一条数据1.1.3. 查询1.1.3.1. 查询所有数据查询一条数据1.1.3.2. 读取特定位置的数据1.1.4. 修改数据1.1.5. 删除数据1. 简介 从Python3.x版本开始&#xff0c;在标准库中已经内置了SQLlite3模块&#xff0c;它可…

Redis中的哨兵机制

有了主从复制的实现以后,我们如果想对主从服务器进行监控,那么在redis2.6以后提供了一个 “哨兵” 的机制,在2.6版本中的哨兵为1.0版本,并不稳定,会出现各种各样的向题,在2.8以后的版本哨兵功能才稳定起来。 顾名思义,哨兵的含义就是监控Redis系统的运行状况。其主要功…

STM32/51单片机实训day6——Proteus8.6版本+ STM32F103驱动LCD12864显示Keil5程序设计

内 容&#xff1a;实现LCD显示 学 时&#xff1a;4学时 知识点&#xff1a;LCD12864芯片介绍&#xff0c;读写操作时序&#xff0c;电路设计 重点&#xff1a; 读写操作时序 难点&#xff1a;读写操作时序 时间&#xff1a;2022年12月26日 9:00&#xff5e;11:50 总结&…

全国产龙芯2K0500多功能SoC处理器及其解决方案

龙芯2K0500片内集成单个64位龙架构(LoongArch)LA264处理器核、32KB一级指令缓存、32KB一级数据缓存、512KB二级缓存、32位DDR2/3-1066控制器、2DGPU图形核心、DVO显示接口、两路PCIe2.0、两路SATA2.0、四路USB2.0、一路USB3.0、两路GMAC、PCI总线、彩色黑白打印接口、HDA及其他…

有备无患!DBS高性价比方案助力富途证券备份上云

“某中心受病毒攻击&#xff0c;导致服务中断&#xff0c;线上业务被迫暂停” “某公司员工误操作删库&#xff0c;核心业务数据部分丢失&#xff0c;无法完全找回” “由于服务器断线&#xff0c;某医院信息系统瘫痪近4小时&#xff0c;期间病人无法使用医保卡挂号和结算” …

Talk预告 | 微软高级研究员杨征元:统一的视觉语言模型

本期为TechBeat人工智能社区第467期线上Talk&#xff01; 北京时间12月29日(周四)20:00&#xff0c;微软高级研究员——杨征元的Talk将准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “统一的视觉语言模型”&#xff0c;届时将从一个统一的角度概述视觉语…

深度循环神经网络

在深度循环神经网络中&#xff0c;隐状态的信息被传递到当前层的下一时间步和下一层的当前时间步。 有许多不同风格的深度循环神经网络&#xff0c; 如长短期记忆网络、门控循环单元、或经典循环神经网络。 这些模型在深度学习框架的高级API中都有涵盖。 总体而言&#xff0c…

第三方库react-redux基础使用 容器UI组件使用 数据管理优化

其实redux并不是React特有的技术 redux是一家独立公司 做出来 适配与目前几大前端主流框架的状态管理工具。 其实 最初 redux也希望码友们用它来管理vue的状态数据 但后面 React官方发现 很多人喜欢在React项目中使用redux 于是 React公司专门做了react-redux这个第三方的库 帮…

【计组】数据通路和流水线设计--《深入浅出计算机组成原理》(三)

课程链接&#xff1a;深入浅出计算机组成原理_组成原理_计算机基础-极客时间 目录 一、建立数据通路 &#xff08;一&#xff09;组合逻辑电路 1、指令周期 2、数据通路 3、CPU所需硬件电路 &#xff08;二&#xff09;时序逻辑电路 1、时序逻辑电路可以解决的问题 二…