【Java数据结构 -- 时间和空间复杂度】
时间和空间复杂度
- 1. 算法效率
- 2. 时间复杂度
- 2.1 时间复杂度的概念
- 2.2 大O的渐进表示法
- 2.3 推导大O阶方法
- 2.4 常见时间复杂度计算举例
- 例1
- 例2
- 例3
- 例4 计算 bubbleSort的时间复杂度
- 例5 计算binarySearch的时间复杂度?
- 例6 计算阶乘递归factorial的时间复杂度?
- 例7 计算斐波那契递归fibonacci的时间复杂度?
- 3. 空间复杂度
- 例1 计算bubbleSort的空间复杂度?
- 例2 计算fibonacci的空间复杂度?
- 例3 计算阶乘递归Factorial的空间复杂度?
- 4. 总结
1. 算法效率
算法效率分为两种:第一种是时间效率,第二种是空间效率。时间效率被称为时间复杂度,而空间效率被称作空间复杂度。时间复杂度主要衡量的是一个算法的运行速度,而空间复杂度主要衡量一个算法所需要的额外空间,在计算机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。
2. 时间复杂度
2.1 时间复杂度的概念
时间复杂度的定义:在计算机科学中,算法的时间复杂度是一个数学函数,它定量描述了该算法的运行时间。一个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知道。但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个分析方式。一个算法所花费的时间与其中语句的执行次数成正比例,算法中的基本操作的执行次数,为算法的时间复杂度,即一个算法的运行时间和这个算法当中的语句执行次数有关系,语句执行次数越多,运行时间就多,成正比的一个关系。
2.2 大O的渐进表示法
// 请计算一下func1基本操作执行了多少次?//F(N) = n^2 + 2n + 10 O(n^2)void func1(int N) {int count = 0;for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {count++; //n+n+n+...+n 即n*n=n^2}}for (int k = 0; k < 2 * N; k++) {count++; //2n}int M = 10;while ((M--) > 0) {count++; //10}System.out.println(count);}
Func1执行的基本操作次数:
F(N) = N^2 + 2*N + 10
实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要大概执行次数,那么这里我们使用大O的渐进表示法。
大O符号(Big O notation):是用于描述函数渐进行为的数学符号
2.3 推导大O阶方法
1、用常数1取代运行时间中的所有加法常数。
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。
使用大O的渐进表示法以后,即随着N越来越大时 10和2*n会很小可以省略,Func1的时间复杂度为:O(N^2)
通过上面我们会发现大O的渐进表示法去掉了那些对结果影响不大的项,简洁明了的表示出了执行次数。
另外有些算法的时间复杂度存在最好、平均和最坏情况:
最坏情况:任意输入规模的最大运行次数(上界)
平均情况:任意输入规模的期望运行次数
最好情况:任意输入规模的最小运行次数(下界)
例如:在一个长度为N数组中搜索一个数据x
最好情况:1次找到
最坏情况:N次找到
平均情况:N/2次找到
在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)
2.4 常见时间复杂度计算举例
时间复杂度的计算需要配合逻辑来看的
例1
// 计算func2的时间复杂度?//F(N) = 2n + 10 O(N)=nvoid func2(int N) {int count = 0;for (int k = 0; k < 2 * N ; k++) {count++; // 2n}int M = 10;while ((M--) > 0) {count++; //10}System.out.println(count);}
例2
// 计算func3的时间复杂度?// n+m = O(n+m)void func3(int N, int M) {int count = 0;for (int k = 0; k < M; k++) {count++; //m}for (int k = 0; k < N ; k++) {count++; //n}System.out.println(count);}
例3
// 计算func4的时间复杂度?// O(1)void func4(int N) {int count = 0;for (int k = 0; k < 100; k++) {count++; // 100}System.out.println(count);}
例4 计算 bubbleSort的时间复杂度
O(n^2),而在最好情况下就是原本就是已经排好的顺序,O(n)
// 计算bubbleSort的时间复杂度?//F(N)=(1+n-1)*(n-1)/2 = 1/2*n^2 - 1/2*n = n^2 即O(n^2)void bubbleSort(int[] array) {for (int end = array.length; end > 0; end--) { //Nboolean sorted = true;for (int i = 1; i < end; i++) { // n-1 + n-2 + ..+2+1//即当end的值不一样 执行的次数也不一样 (1+n-1)*(n-1)/2if (array[i - 1] > array[i]) {Swap(array, i - 1, i);sorted = false;}}if (sorted == true) {break;}}}private void Swap(int[] array, int i, int i1) {}
例5 计算binarySearch的时间复杂度?
二分查找 一次砍一半 --> n n/2 n/4 … 1 即n/2^x=1 --> n=2^x 即log2^n
O(log2^n)
// 计算binarySearch的时间复杂度?// 二分查找 一次砍一半 --> n n/2 n/4 ... 1 即n/2^x=1 --> n=2^x 即log2^n// O(log2^n)int binarySearch(int[] array, int value) {int begin = 0;int end = array.length - 1; //n-1while (begin <= end) {int mid = begin + ((end-begin) / 2);if (array[mid] < value)begin = mid + 1;else if (array[mid] > value)end = mid - 1;elsereturn mid;}return -1;}
例6 计算阶乘递归factorial的时间复杂度?
递归的时间复杂度 = 递归的次数 * 每次递归后执行的次数
O(n)
// 计算阶乘递归factorial的时间复杂度?// 递归的时间复杂度 = 递归的次数 * 每次递归后执行的次数// O(n)long factorial(int N) { // n// 三目运算符不是循环 是一个判断 执行的次数是1return N < 2 ? N : factorial(N-1) * N;}
例7 计算斐波那契递归fibonacci的时间复杂度?
F(N) -> F(N-1) F(N-2) -> F(N-2) F(N-3) F(N-3) F(N-4)
1+2+4+...+2^(n-1) = 2^(n-1)-1 即 O(2^n)
O(2^n)
// 计算斐波那契递归fibonacci的时间复杂度?// F(N) -> F(N-1) F(N-2) -> F(N-2) F(N-3) F(N-3) F(N-4)// 2^0=1 2^1=2 2^2=4 ... 2^(n-1)// 1+2+4+...+2^(n-1) = 2^(n-1)-1 即 O(2^n)int fibonacci(int N) {return N < 2 ? N : fibonacci(N-1)+fibonacci(N-2);}
3. 空间复杂度
空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度 。空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计算规则基本跟时间复杂度类似,也使用大O渐进表示法。
例1 计算bubbleSort的空间复杂度?
O(1)
// 计算bubbleSort的空间复杂度?// 有临时变量 没有申请其它数组 O(1)void bubbleSort(int[] array) {for (int end = array.length; end > 0; end--) {boolean sorted = true;for (int i = 1; i < end; i++) {if (array[i - 1] > array[i]) {Swap(array, i - 1, i);sorted = false;}}if (sorted == true) {break;}}}private void Swap(int[] array, int i, int i1) {}
例2 计算fibonacci的空间复杂度?
// 计算fibonacci的空间复杂度?// 动态开辟了N个空间// O(n)long[] fibonacci(int n) {long[] fibArray = new long[n + 1]; // 重新申请了一个数组来存放数据fibArray[0] = 0;fibArray[1] = 1;for (int i = 2; i <= n ; i++) {fibArray[i] = fibArray[i - 1] + fibArray [i - 2];}return fibArray;}
例3 计算阶乘递归Factorial的空间复杂度?
// 计算阶乘递归Factorial的空间复杂度?// 递归调用了N次,开辟了N个栈帧,每个栈帧使用了常数个空间 O(n)long factorial(int N) {return N < 2 ? N : factorial(N-1)*N;}
4. 总结
- 结合代码的实现去做 空间和时间复杂度的计算
- 一些常用的复杂度大小:
O(1) < O(log2^n) < O(n) < O(n*log2的n次) < O(n的平方)
相关文章:
【Java数据结构 -- 时间和空间复杂度】
时间和空间复杂度 1. 算法效率2. 时间复杂度2.1 时间复杂度的概念2.2 大O的渐进表示法2.3 推导大O阶方法2.4 常见时间复杂度计算举例例1例2例3例4 计算 bubbleSort的时间复杂度例5 计算binarySearch的时间复杂度?例6 计算阶乘递归factorial的时间复杂度?…...
【每日一题】1457. 二叉树中的伪回文路径-2023.11.25
题目: 1457. 二叉树中的伪回文路径 给你一棵二叉树,每个节点的值为 1 到 9 。我们称二叉树中的一条路径是 「伪回文」的,当它满足:路径经过的所有节点值的排列中,存在一个回文序列。 请你返回从根到叶子节点的所有路…...
能让PDF看起来像是扫描件的Look Scanned
什么是 Look Scanned ? Look Scanned 是一个能够让 PDF 看起来就像是扫描件一样的纯前端网站。你再也不需要麻烦地打印之后扫描了,你所需要的就是鼠标点几下。 这是个挺有意思的软件,但是老苏不确定什么场景下会用到这个软件,如果不想自己搭…...
RT-DETR 更换损失函数之 SIoU / EIoU / WIoU / Focal_xIoU
文章目录 更换方式CIoUDIoUEIoUGIoUSIoUWIoUFocal_CIoUFocal_DIoUFocal_EIoUFocal_GIoUFocal_SIoU提示更换方式 第一步:将ultralytics/ultralytics/utils/metrics.py文件中的bbox_iou替换为如下的代码:class...
代码随想录算法训练营第四十六天 | 139.单词拆分,多重背包,背包问题总结
目录 139.单词拆分 多重背包 背包问题总结 01背包 完全背包 多重背包 139.单词拆分 题目链接:139. 单词拆分 不要求字典中的单词全部使用,但是要求拆分的单词拆分成的每一个子串都是字典中的单词。 (1)dp[ i ] 表示前 i 个字符组成…...
opencv-Canny 边缘检测
Canny边缘检测是一种经典的图像边缘检测算法,它在图像中找到强度梯度的变化,从而识别出图像中的边缘。Canny边缘检测的优点包括高灵敏度和低误检率。 在OpenCV中,cv2.Canny() 函数用于执行Canny边缘检测。 基本语法如下: edges…...
案例023:基于微信小程序的童装商城的设计与实现
文末获取源码 开发语言:Java 框架:SSM JDK版本:JDK1.8 数据库:mysql 5.7 开发软件:eclipse/myeclipse/idea Maven包:Maven3.5.4 小程序框架:uniapp 小程序开发软件:HBuilder X 小程序…...
Ansible的循环:loop,with_<lookup>和until
环境 管理节点:Ubuntu 22.04控制节点:CentOS 8Ansible:2.15.6 循环的方法 loopwith_<lookup>until 用这几种方式都可以实现循环。其中, loop 是推荐的用法,在很多时候能够替换 with_<lookup> 。 loop…...
点云 surface 方法总结
点云的表面方法是指通过点云数据来估计和重建物体或场景的表面几何形状。下面总结了几种常见的点云表面方法: 三角化:三角化是最常用的点云表面重建方法之一。它将点云中的点连接成三角形网格,从而重建出物体或场景的表面。常见的三角化算法…...
深入探索Linux文件系统:属性、路径与隐藏之谜
🎥 屿小夏 : 个人主页 🔥个人专栏 : Linux系统理论 🌄 莫道桑榆晚,为霞尚满天! 文章目录 📑前言🌤️文件的组成☁️文件属性☁️文件内容☁️注意事项 🌤️路…...
梯度详解与优化实战
什么是梯度 对所有自变量求偏微分构成的向量,它是一个向量(有大小和函数值增长方向) 导数是一个标量 找最小值点坐标的案例 import torchimport numpy as np import matplotlib.pyplot as plt def himmelblau(x):return (x[0]**2x[1]-11)…...
OSG编程指南<十二>:OSG二三维文字创建及文字特效
1、字体基础知识 适当的文字信息对于显示场景信息是非常重要的。在 OSG 中,osgText提供了向场景中添加文字的强大功能,由于有第三方插件 FreeType 的支持,它完全支持TrueType 字体。很多人可能对 FreeType 和 TrueType 还不太了解,…...
visionOS空间计算实战开发教程Day 6 拖拽和点击
在之前的学习中我们在空间中添加了3D模型,但在初始摆放后就无法再对其进行移动或做出修改。本节我们在Day 5显示和隐藏的基础上让我们模型可以实现拖拽效果,同时对纯色的立方体实现点击随机换色的功能。 首先是入口文件,无需做出改变…...
C# APS.NET CORE 6.0 WEB API IIS部署
1.创建 APS.NET CORE6.0 WEB API项目 默认选项即可 源代码: 项目文件展开: launchSettings.json {"$schema": "https://json.schemastore.org/launchsettings.json","iisSettings": {"windowsAuthentication"…...
C/C++ 常用加密与解密算法
计算机安全和数据隐私是现代应用程序设计中至关重要的方面。为了确保数据的机密性和完整性,常常需要使用加密和解密算法。C是一种广泛使用的编程语言,提供了许多加密和解密算法的实现。本文将介绍一些在C中常用的加密与解密算法,这其中包括Xo…...
从Qt源码的角度分析Qt对象树与内存管理模式
作者:令狐掌门 技术交流QQ群:675120140 csdn博客:https://mingshiqiang.blog.csdn.net/ 文章目录 一、Qt对象树(Object Tree)和父子关系二、源码角度:QObject的内存管理构造函数析构函数addChild() 和 removeChild()三、C++模拟实现Qt的对象树内存管理模式Qt框架提供了一…...
MySQL与Redis如何保证数据的一致性
文章目录 MySQL与Redis如何保证数据的一致性?不好的方案1. 先写 MySQL,再写 Redis2. 先写 Redis,再写 MySQL3. 先删除 Redis,再写 MySQL 好的方案4. 先删除 Redis,再写 MySQL,再删除 Redis5. 先写 MySQL&am…...
micropython - espnow
espnow这个东西可以很简单的进行多设备近距离互联,连握手都不用注册一下就能发信息 目前8266那个8角的刷20231105的1M的固件可以运行 8266目前没有信号强度功能所以我自己写的类强度返回为0 我写的类实例化后最后注册谁发消息就是给谁而接收端则是什么都接ÿ…...
京东数据采集(京东数据运营):怎样快速获取京东市场大数据?
相信京东平台的很多品牌方们都有做数据分析的需求,但面对多而杂的市场数据,很多运营者都没有思路。单依靠肉眼来看,很多商品的类目、销售成绩、价格分布等运营者也未必清楚。 其实对于京东平台上市场数据的获取,品牌可以直接借助一…...
重生奇迹mu迷宫攻略
重生奇迹mu迷宫是一种比较有挑战性的游戏玩法,需要一定的技巧和策略才能完成。以下是一些基本的攻略和技巧: 了解每个迷宫的特点:不同的迷宫有不同的规则和特点,需要根据迷宫的特点来制定合理的策略。在进入迷宫前可以先了解一下…...
3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
