Java数据结构----时间和空间复杂度

目录

1.算法效率

2.时间复杂度

2.1 时间复杂度的概念

2.2 大O的渐进表示法

2.3 推导大O阶方法

3.4 常见时间复杂度计算举例

3.空间复杂度


1.算法效率

算法效率分析分为两种:第一种是时间效率,第二种是空间效率。时间效率被称为时间复杂度,而空间效率被称作空间复杂度。 时间复杂度主要衡量的是一个算法的运行速度,而空间复杂度主要 衡量一个算法所需要的额外空间,在计算机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。


2.时间复杂度

2.1 时间复杂度的概念

时间复杂度的定义:在计算机科学中,算法的时间复杂度是一个数学函数,它定量描述了该算法的运行时间。一个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知道。但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个分析方式。一个算法所花费的时间与其中语句的执行次数成正比例,算法中的基本操作的执行次数,为算法的时间复杂度。

2.2 大O的渐进表示法

// 请计算一下func1基本操作执行了多少次?
void func1(int N){
        int count = 0;
        for (int i = 0; i < N ; i++) {
                for (int j = 0; j < N ; j++) {
                        count++;
                }
        }

        for (int k = 0; k < 2 * N ; k++) {
                count++;
        }
        int M = 10;
        while ((M--) > 0) {
                count++;
        }
        System.out.println(count);
}

Func1 执行的基本操作次数 :

  • N = 10 F(N) = 130
  • N = 100 F(N) = 10210
  • N = 1000 F(N) = 1002010

实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要大概执行次数,那么这里我们使用大O的渐进表示法。
大O符号(Big O notation):是用于描述函数渐进行为的数学符号。

2.3 推导大O阶方法

1、用常数1取代运行时间中的所有加法常数。
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。
使用大O的渐进表示法以后,Func1的时间复杂度为:

  • N = 10 F(N) = 100
  • N = 100 F(N) = 10000
  • N = 1000 F(N) = 1000000

通过上面我们会发现大O的渐进表示法去掉了那些对结果影响不大的项,简洁明了的表示出了执行次数。
另外有些算法的时间复杂度存在最好、平均和最坏情况:

  • 最坏情况:任意输入规模的最大运行次数(上界)
  • 平均情况:任意输入规模的期望运行次数
  • 最好情况:任意输入规模的最小运行次数(下界)

例如:在一个长度为N数组中搜索一个数据x

  • 最好情况:1次找到
  • 最坏情况:N次找到
  • 平均情况:N/2次找到

在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)。

3.4 常见时间复杂度计算举例

// 计算func2的时间复杂度?
void func2(int N) {
        int count = 0;
        for (int k = 0; k < 2 * N ; k++) {
                count++;
        }
        int M = 10;
        while ((M--) > 0) {
                count++;
        }
        System.out.println(count);
}

//答案:O(N)

// 计算func3的时间复杂度?
void func3(int N, int M) {
        int count = 0;
        for (int k = 0; k < M; k++) {
                count++;
        }
        for (int k = 0; k < N ; k++) {
                count++;
        }
        System.out.println(count);
}

//答案:O(N+M)

// 计算func4的时间复杂度?
void func4(int N) {
        int count = 0;
        for (int k = 0; k < 100; k++) {
                count++;
        }
        System.out.println(count);
}

//答案:O(1)

// 计算bubbleSort的时间复杂度?
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;
                }
        }

//答案:O(N^2)  ---等差数列求和

// 计算binarySearch的时间复杂度?
int binarySearch(int[] array, int value) {
        int begin = 0;
        int end = array.length - 1;
        while (begin <= end) {
                int mid = begin + ((end-begin) / 2);
                if (array[mid] < value)
                        begin = mid + 1;
                else if (array[mid] > value)
                        end = mid - 1;
                else
                        return mid;
        }
        return -1;
}

//答案:O(N) = \log_{2}N

 

// 计算阶乘递归factorial的时间复杂度?
long factorial(int N) {
        return N < 2 ? N : factorial(N-1) * N;
}

//答案:O(N)

 // 计算斐波那契递归fibonacci的时间复杂度?
int fibonacci(int N) {
        return N < 2 ? N : fibonacci(N-1)+fibonacci(N-2);
}

//答案:O(2^n)--等比数列求和

 【实例答案及分析】

  • 1. 实例1基本操作执行了2N+10次,通过推导大O阶方法知道,时间复杂度为 O(N)。
  • 2. 实例2基本操作执行了M+N次,有两个未知数M和N,时间复杂度为 O(N+M)。
  • 3. 实例3基本操作执行了100次,通过推导大O阶方法,时间复杂度为 O(1)。
  • 4. 实例4基本操作执行最好N次,最坏执行了(N*(N-1))/2次,通过推导大O阶方法+时间复杂度一般看最坏,时间复杂度为 O(N^2)。
  • 5. 实例5基本操作执行最好1次,最坏 次,时间复杂度为 O(\log_{2}N ) ps: 在算法分析中表示是底数为2,对数为N,有些地方会写成lgN。(建议通过折纸查找的方式讲解logN是怎么计算出来的)(因为二分查找每次排除掉一半的不适合值,一次二分剩下:n/2两次二分剩下:n/2/2 = n/4)
  • 6. 实例6通过计算分析发现基本操作递归了N次,时间复杂度为O(N)。
  • 7. 实例7通过计算分析发现基本操作递归了 次,时间复杂度为O( 2^N)。(建议画图递归栈帧的二叉树讲解)

3.空间复杂度

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度 。空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计算规则基本跟时间复杂度类似,也使用大O渐进表示法

// 计算bubbleSort的空间复杂度?
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;
                }

        }
}

//答案:O(1)

// 计算fibonacci的空间复杂度?
int[] 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;
}

//答案:O(n)。

// 计算阶乘递归Factorial的空间复杂度?
long factorial(int N) {
        return N < 2 ? N : factorial(N-1)*N;
}

//答案:O(N)

【实例答案及分析】

  • 1. 实例1使用了常数个额外空间,所以空间复杂度为 O(1)。
  • 2. 实例2动态开辟了N个空间,空间复杂度为 O(N)。
  • 3. 实例3递归调用了N次,开辟了N个栈帧,每个栈帧使用了常数个空间。空间复杂度为O(N)。

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

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

相关文章

手机通用便签APP哪个比较好用?

手机通用便签APP哪个比较好用&#xff1f;随着现代科技的不断发展&#xff0c;手机的更新换代频率是比较快的&#xff0c;基本两三年就会换新手机。其中Android和iOS系统为手机主要使用系统&#xff0c;有些用户在使用一个系统腻了后&#xff0c;通常想更换另一个系统的品牌手机…

哪些行业适合做小程序?零售电商、餐饮娱乐、旅游酒店、教育生活、医疗保健、金融社交、体育健身、房产汽车、企管等,你的行业在其中么?

引言 在当今数字化时代&#xff0c;小程序成为了各行各业快速发展的数字工具之一。它的轻便、灵活的特性使得小程序在多个行业中找到了广泛的应用。本文将探讨哪些行业适合开发小程序&#xff0c;并介绍各行业中小程序的具体应用。 一、零售和电商 在当今数字化的商业环境中&…

select a,b,c from 表 where b=1 and c=1; abc是联合索引,这样查询会命中索引吗?

如果select 只显示索引列 那么会命中索引 如果select * 那么不会走索引&#xff0c;会查全表

Linux系统中前后端分离项目部署指南

目录 一.nginx安装以及字启动 解压nginx 一键安装4个依赖 安装nginx 启动 nginx 服务 开放端口号 并且在外部访问 设置nginx自启动 二.配置负载均衡 1.配置一个tomact 修改端口号 8081端口号 2.配置负载均衡 ​编辑 三.部署前后端分离项目 1.项目部署后端 ​编辑…

互联网加竞赛 大数据房价预测分析与可视

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 大数据房价预测分析与可视 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;4分 该项目较为新颖&#xff0c;适合…

国产替代MATLAB的征途

国产替代MATLAB的征途 The Journey of Domestic Alternatives to MATLAB 在科技的浪潮中&#xff0c;软件成为了推动进步的重要工具。MATLAB&#xff0c;这一工程和科学计算的巨擘&#xff0c;因其强大的数值分析、矩阵运算能力和丰富的应用工具箱&#xff0c;在全球学术界和工…

【c语言】字符函数和字符串函数(上)

前言 在编程的过程中&#xff0c;我们经常要处理字符和字符串&#xff0c;为了⽅便操作字符和字符串&#xff0c;C语⾔标准库中提供了⼀系列库函数~ 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 前言 1. 字符分…

nginx 第三方模块 与变量

一&#xff0c; 网页的状态页 详细见上一章 《nginx 配置文件详细介绍》 二&#xff0c;Nginx 第三方模块 开源 不是官方模块 别人写的 你编译进nginx&#xff08;./configure 这一步添加的模块&#xff09; &#xff08;一&#xff09;ehco 模块 这边以echo 模块为…

MySQL-行转列,链接查询

1. 行转列 1.1 示例数据准备 create table test_9(id int,name varchar(22),course varchar(22),score decimal(18,2) ); insert into test_9 (id,name,course,score)values(1,小王,java,99); insert into test_9 (id,name,course,score)values(2,小张,java,89.2); inse…

RocketMQ - 消息中间件路由中心的架构原理

1. NameServer到底可以部署几台机器 要部署RocketMQ&#xff0c;就得先部署NameServer&#xff0c;那么NameServer到底可以部署几台机器呢&#xff1f;是一台机器还是可以部署多台机器&#xff0c;如果部署多台机器&#xff0c;他们之间是怎么协同工作的&#xff1f; NameSer…

备战蓝桥杯————递归反转单链表

当要求只反转单链表中的一部分时&#xff0c;递归实现确实具有一定的挑战性&#xff0c;但也是可行的。下面我将介绍一种递归实现的方法来反转单链表中的一部分。 一、反转链表 题目描述 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示…

Mac 下 Python+Selenium 自动上传西瓜视频

背景 研究下 PythonSelenium 自动化测试框架&#xff0c;简单实现 Mac 下自动化批量上传视频西瓜视频并发布&#xff0c;分享给需要的同学&#xff08;未做过多的异常处理&#xff09;。 脚本实现 首先通过手工手机号登录&#xff0c;保存西瓜视频网站的 cookie 文件 之后加载…

基于java在线调查表单系统

基于java在线调查表单系统 一、演示效果二、特性汇总三、下载链接 一、演示效果 二、特性汇总 多种技术方案&#xff0c;满足不同的技术选型需求完善的浏览器兼容、保证传统客户也能正常使用部署简单&#xff0c;一行命令完成部署更新方便&#xff0c;直接替换原安装文件不用担…

通过二叉树例题深入理解递归问题

目录 引入&#xff1a; 例1&#xff1a;二叉树的前序遍历&#xff1a; 例2&#xff1a; N叉树的前序遍历&#xff1a; 例3&#xff1a;二叉树的最大深度&#xff1a; 例4&#xff1a;二叉树的最小深度 例5&#xff1a;N叉树的最大深度&#xff1a; 例6&#xff1a;左叶子…

基于Springboot的旅游网管理系统设计与实现(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的旅游网管理系统设计与实现&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层…

ui设计:利用即使设计设计出漂亮样式

目录 一、基本操作 二、具体介绍 6-1 填充图片 6-2 填充色 6-3 图标 右边栏基础设置 右边栏导出​编辑 一、基本操作 二、具体介绍 6-1 填充图片 选择其一图片填充 6-2 填充色 6-3 图标 右边栏基础设置 右边栏导出

C++17之折叠表达式

相关文章系列 深入理解可变参数(va_list、std::initializer_list和可变参数模版) 目录 1.介绍 2.应用 2.1.使用折叠表达式 2.2.支持的运算符 2.3.使用折叠处理类型 3.总结 1.介绍 折叠表达式是C17新引进的语法特性。使用折叠表达式可以简化对C11中引入的参数包的处理&…

自定义el-upload 上传文件

前言 最近在做一个文件上传的功能&#xff0c;后端接口写好了、发现前端上传文件的页面不会写……&#xff08;我很笨的&#xff09;然后我就找啊找发现element有个组件是<el-upload/>能直接上传文件。我就想直接用拿来改改改成自己想要的&#xff0c;可是就是这样我花了…

【C++】拷贝构造函数(深拷贝和浅拷贝)

使用场景 在C类中&#xff0c;我们在类的成员变量内定义了一个指针。这时我们需要去创建它的拷贝构造函数&#xff0c;否则编译器会为这个类创建默认的拷贝构造函数&#xff0c;而默认拷贝构造函数会导致浅拷贝问题&#xff1b;浅拷贝可能会会导致内存泄漏问题&#xff0c;也可…

MATLAB Function转C代码实战

文章目录 前言1. 准备工作2. 使用MATLAB Coder2.1 确定输入输出的类型2.2 MATLAB Coder过程 3. 代码调整和优化4. 编译和测试5. 性能分析和优化结语 前言 在科学与工程领域&#xff0c;MATLAB&#xff08;Matrix Laboratory&#xff09;是一种广泛使用的高级技术计算软件&…