算法的时间及空间复杂度

news2025/1/11 2:44:56

🍓 简介:java系列技术分享(👉持续更新中…🔥)
🍓 初衷:一起学习、一起进步、坚持不懈
🍓 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正🙏
🍓 希望这篇文章对你有所帮助,欢迎点赞 👍 收藏 ⭐留言 📝

🍓 更多文章请点击
在这里插入图片描述在这里插入图片描述

文章目录

  • 一、 什么是算法?
  • 二、 算法初体验
    • 案例1 计算1到100的和。
    • 案例2 计算10的阶乘
  • 三、 算法的复杂度分析
    • 3.1 时间复杂度分析
      • 3.1.1 案例 计算1到100的和,逐行解析
      • 3.1.2 算法时间复杂度
        • 3.1.2.1 大O记法
        • 3.1.2.2. 最坏情况
    • 3.2 空间复杂度分析

一、 什么是算法?

  • 能够对一定规范的输入,在有限时间内获得所要求的输出
  • 不同的算法可能用不同的时间、空间或效率来完成同样的任务。
  • 一个算法的优劣可以用空间复杂度时间复杂度来衡量。

二、 算法初体验

一个优秀的算法追求以下两个目标:

  1. 花最少的时间完成需求
  2. 占用最少的内存空间完成需求

案例1 计算1到100的和。

第一种解法

public static void main(String[] args) { 
    int sum = 0;
    int n=100;
    for (int i = 1; i <= n; i++) {
        sum += i;
    }  
    System.out.println("sum=" + sum);
}

第二种解法

 public static void main(String[] args) {
        int sum = 0;
        int n=100;
        sum = (n+1)*n/2;
        System.out.println("sum="+sum);
}

很明显,第二种算法完成需求,花费的时间更少一些。

案例2 计算10的阶乘

第一种解法

public class Test {
    public static void main(String[] args) {
        //测试,计算10的阶乘
        long result = fun1(10);
        System.out.println(result);
    }
    //计算n的阶乘
    public static long fun1(long n){
        if (n==1){
            return 1;
        }
        return n*fun1(n-1);
    }
}

第二种解法

public class Test {
    public static void main(String[] args) {
        //测试,计算10的阶乘
        long result = fun2(10);
        System.out.println(result);
    }
    //计算n的阶乘
    public static long fun2(long n){
        int result=1;
        for (long i = 1; i <= n; i++) {
            result*=i;
        }
        return result;
    }
}

第一种解法,使用递归完成需求,fun1方法会执行10次,并且第一次执行未完毕,调用第二次执行…最终,最多的时候,需要在栈内存同时开辟10块内存分别执行10个fun1方法。

第二种解法,使用for循环完成需求,fun2方法只会执行一次,最终,只需要在栈内存开辟一块内存执行fun2方法即可。

很明显,第二种算法完成需求,占用的内存空间更小。

三、 算法的复杂度分析

3.1 时间复杂度分析

事后分析估算方法:
这种方法有很大的缺陷:必须依据算法实现编制好的测试程序,通常要花费大量时间和精力,测试完了如果发现测试的是非常糟糕的算法,那么之前所做的事情就全部白费了,并且不同的测试环境(硬件环境)的差别导致测试的结果差异也很大。
事前分析估算方法:
在计算机程序编写前,依据统计方法对算法进行估算,这包括对算法的时间复杂度进行分析,以了解算法随问题规模n的变化情况并确定其数量级。这种分析可以帮助程序员在编写代码之前预测代码的运行时间,从而更好地优化代码和数据结构,提高代码运行效率。

3.1.1 案例 计算1到100的和,逐行解析

第一种
如果输入量n为1亿,则需要计算1亿次;

public static void main(String[] args) {
    int sum = 0;//执行1次
    int n=100;//执行1次
    for (int i = 1; i <= n; i++) {//执行了n+1次
        sum += i;//执行了n次
    }
    System.out.println("sum=" + sum);
}

第二种
如果输入量n为1亿,则需要计算1次;

public static void main(String[] args) {
        int sum = 0;//执行1次
        int n=100;//执行1次
        sum = (n+1)*n/2;//执行1次
        System.out.println("sum="+sum);
}

经过一系列的研究,通过函数渐近增长分析,这里将结论总结如下:

比较算法随着输入规模的增长量时,可以有以下规则:

1.算法函数中的常数可以忽略;

2.算法函数中最高次幂的常数因子可以忽略;

3.算法函数中最高次幂越小,算法效率越高。

3.1.2 算法时间复杂度

3.1.2.1 大O记法

​在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随着n的变化情况并确定T(n)的量级。算法的时间复杂度,就是算法的时间量度,记作:T(n)=O(f(n))。它表示随着问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐近时间复杂度,简称时间复杂度,其中f(n)是问题规模n的某个函数。
用大写O()来体现算法时间复杂度的记法,我们称之为大O记法。一般情况下,随着输入规模n的增大,T(n)增长最慢的算法为最优算法。

下面我们使用大O表示法来表示一些求和算法的时间复杂度:
如果忽略判断条件的执行次数和输出语句的执行次数,那么当输入规模为n时,以上算法执行的次数分别为:
​算法一:3次
算法二:n+3次
​算法三:n^2+2次

如果用大O记法表示上述每个算法的时间复杂度,应该如何表示呢?基于我们对函数渐近增长的分析,推导大O阶的表示法有以下几个规则可以使用:

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

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

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

所以,上述算法的大O记法分别为:

​ 算法一:O(1)
​ 算法二:O(n)
​ 算法三:O(n^2)

3.1.2.2. 最坏情况

有一个存储了n个随机数字的数组,请从中查找出指定的数字。

public int search(int num){
    int[] arr={11,10,8,9,7,22,23,0};
    for (int i = 0; i < arr.length; i++) {
        if (num==arr[i]){
            return i;
        }
    }
    return -1;
}

最好情况:

​ 查找的第一个数字就是期望的数字,那么算法的时间复杂度为O(1)

最坏情况:

​ 查找的最后一个数字,才是期望的数字,那么算法的时间复杂度为O(n)

平均情况:

​ 任何数字查找的平均成本是O(n/2)

最坏情况是一种保证,在应用中,这是一种最基本的保障,即使在最坏情况下,也能够正常提供服务,所以,除非特别指定,我们提到的运行时间都指的是最坏情况下的运行时间。

3.2 空间复杂度分析

计算机的软硬件都经历了一个比较漫长的演变史,作为为运算提供环境的内存,更是如此,从早些时候的512k,经历了1M,2M,4M…等,发展到现在的8G,甚至16G和32G,所以早期,算法在运行过程中对内存的占用情况也是一个经常需要考虑的问题。我么可以用算法的空间复杂度来描述算法对内存的占用。

1.基本数据类型内存占用情况:

数据类型内存占用字节数
byte1
short2
int4
long8
float4
double8
boolean1
char2
  • 由于现在的计算机设备内存一般都比较大,基本上个人计算机都是4G起步,大的可以达到32G,所以内存占用一般情况下并不是我们算法的瓶颈
  • 注意空间复杂度是衡量算法在运行过程中使用的内存大小,而不是指程序代码本身的大小。因此,在分析空间复杂度时,需要考虑算法在执行过程中所创建的临时变量、数据结构以及其他相关的内存使用情况。
  • 普通情况下直接说复杂度,默认为算法的时间复杂度。
  • 但是,如果你做的程序是嵌入式开发,尤其是一些传感器设备上的内置程序,由于这些设备的内存很小,一般为几kb,这个时候对算法的空间复杂度就有要求了,但是一般做java开发的,基本上都是服务器开发,一般不存在这样的问题。

后续持续更新............................

在这里插入图片描述在这里插入图片描述

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

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

相关文章

thinkPhp5返回某些指定字段

//去除掉密码$db new UserModel();$result $db->field(password,true)->where("username{$params[username]} AND password{$params[password]}")->find(); 或者指定要的字段的数组 $db new UserModel();$result $db->field([username,create_time…

AList dokcer安装及百度网盘挂载

AList是开源的网盘管理工具。本文介绍如何通过docker安装AList并挂载百度网盘 1、AList安装 1.1、系统安装 通过docker命令进行安装&#xff0c;命令如下: docker run -d --restartalways -v /etc/alist:/opt/alist/data -p 5244:5244 --name"alist" xhofe/alist:…

学生来看!如何白嫖内网穿透?点进来!

文章目录 前言本教程解决的问题是&#xff1a;按照本教程方法操作后&#xff0c;达到的效果是前排提醒&#xff1a; 1 搭建虚拟机1.1 下载文件vmvare虚拟机安装包1.2 安装VMware虚拟机&#xff1a;1.3 解压虚拟机文件1.4 虚拟机初始化1.5 没有搜索到解决方式&#xff1a;1.6 虚…

End-to-End Object Detection with Transformers(论文解析)

End-to-End Object Detection with Transformers 摘要介绍相关工作2.1 集合预测2.2 transformer和并行解码2.3 目标检测 3 DETR模型3.1 目标检测集设置预测损失3.2 DETR架构 摘要 我们提出了一种将目标检测视为直接集合预测问题的新方法。我们的方法简化了检测流程&#xff0c…

第三方软件信息安全测评服务范围

安全测试 第三方软件信息安全cnas资质测评服务范围&#xff1a; 1、信息安全风险评估 依据《GB/T 20984-2007 信息安全技术信息安全风险评估规范》&#xff0c;通过风险评估项目的实施&#xff0c;对信息系统的重要资产、资产所面临的威胁、资产存在的脆弱性、已采取的防护措…

企业架构LNMP学习笔记24

学习目标和内容&#xff1a; 1、能够描述高可用HA的作用 2、能够理解VIP的切换&#xff1a;虚拟IP。 3、能够描述keepalived作用&#xff1a;保持活跃。主备的服务器的关系。 4、能够理解主master和备backup服务器关系 5、能够实现主备服务器高可用配置&#xff1a;主服务…

合宙Air724UG LuatOS-Air LVGL API控件-开关 (Switch)

开关 (Switch) 示例代码 function event_handler(obj, event)if event lvgl.EVENT_VALUE_CHANGED thenprint("State", lvgl.switch_get_state(obj))end endsw1 lvgl.switch_create(lvgl.scr_act(), nil) lvgl.obj_align(sw1, nil, lvgl.ALIGN_CENTER, 0, -50) lvg…

超强大JS表格:DataViewsJS 1.8.16.1407 Crack

DataViewsJS完整的 JavaScript 数据呈现和数据网格平台 通过从各种不同的演示视图中进行选择&#xff0c;包括树、卡片、砖石、网格、时间线、甘特图、日历和网格&#xff0c;超越传统的表格显示。 快速地&#xff01;纯 JavaScript&#xff0c;针对速度进行了优化 从多种视图中…

数据结构与算法_树和二叉树

目录 一、树的概念 二、树的衍生概念 三、二叉树 顺序结构 链式存储 二叉树连式结构的遍历 一、树的概念 树是一种非线性的数据结构&#xff0c;它由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。 在树中&#xff0c;有一个特殊节点成为根节…

【GO语言基础】前言

系列文章目录 【Go语言学习】ide安装与配置 【GO语言基础】前言 【GO语言基础】变量常量 【GO语言基础】数据类型 【GO语言基础】运算符 文章目录 系列文章目录一、基础知识包和函数函数声明语法简洁性 括号成对出现GO常用DOS命令命名规则项目目录结构注释 总结 一、基础知识 …

The Sandbox 中的建设者:走进 Sandja Studio

随着 The Sandbox 出版新功能的到来&#xff0c;来自世界各地的熟练建设者正在完成必要的步骤&#xff0c;推出他们的可玩体验并与社区分享。 在本期的《The Sandbox 建设者》中&#xff0c;我们将与Sandja Studio一起讨论他们的《星际考古学家》体验。 Sandja Studio 是一家…

ARM接口编程—UART(exynos 4412平台)

UART简介 UART Universal Asynchronous Receiver Transmitter即通用异步收发器&#xff0c;是一种通用的串行、异步通信总线该总线有两条数据线&#xff0c;可以实现全双工的发送和接收在嵌入式系统中常用于主机与辅助设备之间的通信 波特率 波特率用于描述UART通信时的通信…

企业架构LNMP学习笔记25

高可用服务搭建&#xff1a; HA高可用&#xff1a;是一个解决方案。 高可用HA&#xff08;High Availability&#xff09;是分布式系统架构中必须考虑的因素之一。它通常是指通过设计&#xff0c;减少系统服务不可用的时间&#xff0c;假设系统一直能够提供服务&#xff0c;我…

Navicat连接openGauss数据库报错

错误信息&#xff1a;fe_sendauth:invalid authentication request from server:AUTH_REQ_SASL_CONT without AUTH_REQ_SASL 解决步骤&#xff1a; 1&#xff09;关闭防火墙&#xff1a; 切换root用户执行&#xff1a;su - root 输入密码 systemctl status firewalld 查…

用于独立系统应用的光伏MPPT铅酸电池充电控制器建模(Simulink实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【C++】静态库lib和动态库dll的优缺点、使用方法

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

uniapp 悬浮窗-任意界面 Ba-FloatWinWeb

简介&#xff08;下载地址&#xff09; Ba-FloatWinWeb 是一款支持自定义任意界面的悬浮窗插件。采用webview方式&#xff0c;同时支持本地、网络地址&#xff1b;自带几种界面&#xff0c;可直接使用。 支持显示、更新、隐藏支持记录显示位置支持拖动支持监听点击事件支持自…

查看linux开发板的CPU频率

1&#xff09;查看CPU可设置的频率列表 cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies 2&#xff09;查看CPU当前所使用的频率&#xff1a; cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq 3&#xff09;设置CPU频率&#xff08;最高…

linux常用命令及解释大全(三)

目录 前言 一、字符设置和文件格式转换 二、文件系统分析 三、初始化一个文件系统 四、备份 五、光盘 六、网络 总结 前言 本篇文章继续介绍了一部分linux常用命令&#xff0c;包括字符设置和文件格式转换&#xff0c;文件系统分析&#xff0c;初始化一个文件系统&…