当前位置: 首页 > news >正文

数据结构(Java版)第一期:时间复杂度和空间复杂度

目录

一、数据结构的概念

1.1. 什么是数据结构

1.2. 算法与数据结构的关系 

二、算法效率

三、时间复杂度 

3.1. 大O的渐进表⽰法 

3.2. 计算冒泡排序的时间复杂度

3.3. 计算二分查找的时间复杂度

四、空间复杂度

4.1. 空间复杂度 

4.2. 冒泡排序的空间复杂度

4.3. 斐波那契数列的空间复杂度 

五、学习时间复杂度和空间复杂度的好处


一、数据结构的概念

1.1. 什么是数据结构

       什么是数据结构呢?相信很多老铁尤其是非计算机专业的老铁还是第一次听说这个词。通俗地说,数据结构就是在内存当中对我们的数据进行一个管理和建立数据见关系,我们熟知的内存条(如下图所示)就是存储数据的介质,我们对数据的管理就是存储在内存条上的。

       计算机这个学科最重要的是做软件开发,软件可以帮助我们实现各种功能,比如我们微信好友列表里面,表面上就是一堆姓名的数据,透过计算机我们看到的只是01010,而这些数据就存在内存条上。

1.2. 算法与数据结构的关系 

       算法就是定义良好的计算过程,它取⼀个或⼀组的值为输⼊,并产⽣出⼀个或⼀组值作 为输出。简单来说算法就是利用计算机处理问题的步骤,比如我们对数据进行一个排名,就要用到排序算法,以及需要这个区域来进行排名,就需要堆来实现。

        那么数据结构与算法之间的关系呢?二者相辅相成,你中有我,我中有你。解决一些算法问题需要用到数据结构;实现一些数据结构时,又需要用到一些算法。 

二、算法效率

       如何衡量⼀个算法的好坏,就需要用到算法效率去衡量。算法效率分析分为两种:第⼀种是时间效率,第⼆种是空间效率。时间效率被称为时间复杂度,⽽空 间效率被称作空间复杂度。时间复杂度主要衡量的是⼀个算法的运⾏速度,⽽空间复杂度主要衡量⼀ 个算法所需要的额外空间。

        通俗点说,时间复杂度和空间复杂度用来衡量代码消耗资源开销的多少,衡量的标准应该是与代码有关,与运行的设备无关。  

三、时间复杂度 

       ⼀个算法所花费的时间与其中语句的执⾏次数成正⽐例,算法中的 基本操作的执⾏次数,为算法的时间复杂度。站在数学的角度来看,时间复杂度可以看作是计算关键操作的次数与使用问题规模的函数关系,再对这个函数关系进行一个化简和近似。化简就是只取最高次项,把最高次项的系数也忽略掉,记作O() 。 

         下面博主将结合代码带大家来具体体会一下时间复杂度。

3.1. 大O的渐进表⽰法 

import java.util.Scanner;public class Main {public static int func(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++;}return count;}public static void main(String[] args) {Scanner num = new Scanner(System.in);int b = num.nextInt();int a = func(b);System.out.println(a);}
}

         上面的基本操作就是count的自增,那么count的被执行次数与N的函数关系就是count = N^{2} + 2N + 10。那么我们就要记作O(N^{2})

import java.util.Scanner;public class Main {public static int func(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++;}return count;}public static void main(String[] args) {Scanner num = new Scanner(System.in);int b = num.nextInt();int a = func(b);System.out.println(a);}
}

       上面这段代码的函数关系是count = N^{2} + 10,那么依旧是记作O(N^{2})。随着N值的增大,两个函数的值会越来越接近。

       所以说,计算时间复杂度,一定要先找到核心的基本操作是什么。这个基本操作可能是打印、修改、比较或者是删除。 

        我们下面一段代码,因为描述问题规模的方式,不一定就只有一个变量,也可以是多个。此时我们应该记作O(M + N)

import java.util.Scanner;public class Main {public static int func2(int M,int N){int count = 0;for (int k = 0; k < M; k++) {count++;}for (int k = 0; k < N; k++) {count++;}return count;}public static void main(String[] args) {Scanner num = new Scanner(System.in);int m = num.nextInt();int n = num.nextInt();System.out.println(func2(m, n));}
}

       我们再来看下面一段代码,下面的时间复杂度就比较固定了,基本操作的次数与N无关,无论N是多少,count永远被循环了100次。那么此时的时间复杂度要记作O(1),常数级时间复杂度。及时这里的i<1亿,时间复杂度照样是O(1)

import java.util.Scanner;public class Main {public static int func3(int N){int count = 0;for (int i = 0; i < 100; i++) {count++;}return count;}public static void main(String[] args) {Scanner num = new Scanner(System.in);int a = num.nextInt();System.out.println(func3(a));}
}

         如果说出现了两段代码,一个时间复杂度是O(N),另一个是O(1),那么O(N)不一定比O(1)慢,有可能当N比较小时,时间复杂度要比O(1)。所以说,在这里要牢记时间复杂度衡量的是问题规模和时间的变化趋势,不能直接决定快慢。

3.2. 计算冒泡排序的时间复杂度

public class Main {public static void BubbleSort(int[] arrays){for (int end = arrays.length; end > 0; end--) {boolean sorted = true;for (int i = 0; i < end; i++) {if(arrays[i-1] > arrays[i]){Swap(arrays, i - 1, i);sorted = false;}}if (sorted == true){break;}}}
}

         我们想要计算这个BubbleSort的时间复杂度,同理,首先也要搞清楚基本操作是什么。其中我们调用Swap方法进行交换的时候,在里面是不涉及内嵌循环的,所以计算时间复杂度的时候不用计算Swap内部的交换。我们先看外层循环,起始end的值是数组的长度N;内层循环呢,由于end的值不固定,当end=N时,i循环了N次,当end=N-1时,i循环了N-1次。所以时间复杂度的计算就是N+(N-1)+……+2+1,结果就是O(N^{2})

3.3. 计算二分查找的时间复杂度

public class Main {public static int BinarySearch(int[] arrays,int value){int begin = 0;int end = arrays.length - 1;while(begin <= end){int mid = begin + ((end-begin) / 2);if (arrays[mid] < value){begin = mid + 1;}else if(arrays[mid] > value){end = mid - 1;}else{return mid;}}return -1;}
}

       二分查找,每循环一次,区间就会缩小一半,当区间缩小为1的时候,我们才得出“找到或者是没找到”的结论。我们可能说不好直接得出时间复杂度来,那我们就利用特殊值法。当数组元素为8时,最多要经历4次循环;当数组元素为16时,最多要经历5次循环。所以我们可以得出时间复杂度为2^{循环次数}=N

       对数级别的复杂度,及时问题规模变得很大,核心操作次数增长依然缓慢。 

       综合冒泡排序和二分查找的时间复杂度时,准确地说要涉及到三种情况:1.最好情况下,最需要循环一次就能找到;2.平均情况下,循环一半的次数;3.最坏情况下,循环了最多次。

四、空间复杂度

4.1. 空间复杂度 

        空间复杂度是衡量代码运行中消耗的临时空间,也就是我们的代码在运行时所创建的空间,至运行结束被销毁的空间。比如一个数组,长度为N,在后续代码中,并没有创建任何临时的空间。此时这个数组的空间复杂度就是常数级复杂度O(1)

4.2. 冒泡排序的空间复杂度

​public class Main {public static void BubbleSort(int[] arrays){for (int end = arrays.length; end > 0; end--) {boolean sorted = true;for (int i = 0; i < end; i++) {if(arrays[i-1] > arrays[i]){Swap(arrays, i - 1, i);sorted = false;}}if (sorted == true){break;}}}
}​

       上面的代码都创建了三个临时变量,sorted和i都创建了N次,那么空间复杂度就是2N+1,也就是O(N)。但其实不是的,因为空间和时间不一样,时间是一去不复返的,而空间是可以重复利用的,都是销毁了前一个才创建下一个,前一个和下一个共用同一块空间。一共三个临时变量,所以空间复杂度就是O(1)

4.3. 斐波那契数列的空间复杂度 

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;}

       我们可以看到这次创建了临时空间,方法进来之后才创建,方法出去之后才销毁。下面除了i,也没有创建额外的临时空间了,所以上面代码的空间复杂度才是O(N)

五、学习时间复杂度和空间复杂度的好处

     学习时间复杂度,目的是为了能够正确的使用数据结构。数据结构有很多种,比如数组、队列、哈希表、栈、二叉树以及平衡树等,这些数据结构在不同场景中会有不同的应用。要想知道那种数据结构更合适,就要使用时间复杂度和空间复杂度来衡量。 

相关文章:

数据结构(Java版)第一期:时间复杂度和空间复杂度

目录 一、数据结构的概念 1.1. 什么是数据结构 1.2. 算法与数据结构的关系 二、算法效率 三、时间复杂度 3.1. 大O的渐进表⽰法 3.2. 计算冒泡排序的时间复杂度 3.3. 计算二分查找的时间复杂度 四、空间复杂度 4.1. 空间复杂度 4.2. 冒泡排序的空间复杂度 4.3.…...

基于web的音乐网站(Java+SpringBoot+Mysql)

目录 1系统概述 1.1 研究背景 1.2研究目的 1.3系统设计思想 2相关技术 2.1 MYSQL数据库 2.2 B/S结构 2.3 Spring Boot框架简介 3系统分析 3.1可行性分析 3.1.1技术可行性 3.1.2经济可行性 3.1.3操作可行性 3.2系统性能分析 3.2.1 系统安全性 3.2.2 数据完整性 …...

用go语言后端开发速查

文章目录 一、发送请求和接收请求示例1.1 发送请求1.2 接收请求 二、发送form-data格式的数据示例 用go语言发送请求和接收请求的快速参考 一、发送请求和接收请求示例 1.1 发送请求 package mainimport ("bytes""encoding/json""fmt""ne…...

GeekChallenge 2024 第十五届极客大挑战 pwn AK

GeekChallenge 2024 第十五届极客大挑战 pwn AK &#x1f340;前言☘️ez_shellcode&#xff08;shellcode&#xff0c;栈溢出&#xff09;&#x1f33f;分析&#x1f33f;解题&#x1f33f;exp ☘️买黑吗喽了吗&#xff08;整数溢出&#xff0c;栈溢出&#xff09;&#x1f3…...

禅道是什么,nas是什么,ssh是什么,finalshell是什么,git命令feat 、fix分别什么意思

禅道&#xff08;Zentao&#xff09;是一款开源的项目管理软件&#xff0c;专为软件开发团队设计。它集成了项目管理、产品管理、质量管理、文档管理和事务管理等多种功能&#xff0c;旨在帮助团队提高工作效率和项目交付质量。禅道支持敏捷开发方法&#xff0c;同时也适用于传…...

点云-半径搜索法-Radius Search

核心作用 在于通过设定一个空间范围&#xff08;半径&#xff09;寻找点的邻域点集合&#xff0c;从而支持对局部区域的分析和操作。 因为空间半径不会随着密度变化而改变点云输出的结果&#xff0c;处理密度变化大的点云时很重要。 应用场景 稀疏点检测&#xff1a;当点云密度…...

P11290 【MX-S6-T2】「KDOI-11」飞船

题目大意&#xff1a;有i种加油站&#xff0c;最开始速度为1&#xff0c;每次加油可以使速度*v&#xff0c;每次加油有一个时间代价&#xff0c;求到达终点所需最小时间。 思路&#xff1a;不妨考虑dp&#xff0c;贪心是错误的。 对于速度而言&#xff0c;&#xff0c;所以速…...

WebGIS地图框架有哪些?

地理信息系统&#xff08;GIS&#xff09;已经成为现代应用开发中不可或缺的一部分&#xff0c;尤其在前端开发中。随着Web技术的快速发展&#xff0c;许多强大而灵活的GIS框架涌现出来&#xff0c;为开发人员提供了丰富的工具和功能&#xff0c;使他们能够创建交互式、高性能的…...

量化加速知识点(整理中。。。)

量化的基本概念 通过减少模型中计算精度&#xff0c;从而减少模型计算所需要的访存量。 参考...

BLIP-2模型的详解与思考

大模型学习笔记------BLIP-2模型的详解与思考 1、BLIP-2框架概述2、BLIP-2网络结构详解3、BLIP-2的几点思考 上一篇文章上文中讲解了 BLIP&#xff08;Bootstrapping Language-Image Pretraining&#xff09;模型的一些思考&#xff0c;本文将讲述一个BLIP的升级版 BLIP-2&am…...

2024年11月22日 十二生肖 今日运势

小运播报&#xff1a;2024年11月22日&#xff0c;星期五&#xff0c;农历十月廿二 &#xff08;甲辰年乙亥月庚寅日&#xff09;&#xff0c;法定工作日。 红榜生肖&#xff1a;马、猪、狗 需要注意&#xff1a;牛、蛇、猴 喜神方位&#xff1a;西北方 财神方位&#xff1a…...

小米C++ 面试题及参考答案上(120道面试题覆盖各种类型八股文)

进程和线程的联系和区别 进程是资源分配的基本单位&#xff0c;它拥有自己独立的地址空间、代码段、数据段和堆栈等。线程是进程中的一个执行单元&#xff0c;是 CPU 调度的基本单位。 联系方面&#xff0c;线程是进程的一部分&#xff0c;一个进程可以包含多个线程。它们都用于…...

SQL SELECT 语句:基础与进阶应用

SQL SELECT 语句&#xff1a;基础与进阶应用 SQL&#xff08;Structured Query Language&#xff09;是一种用于管理关系数据库的编程语言。在SQL中&#xff0c;SELECT语句是最常用的命令之一&#xff0c;用于从数据库表中检索数据。本文将详细介绍SELECT语句的基础用法&#…...

微服务即时通讯系统的实现(服务端)----(1)

目录 1. 项目介绍和服务器功能设计2. 基础工具安装3. gflags的安装与使用3.1 gflags的介绍3.2 gflags的安装3.3 gflags的认识3.4 gflags的使用 4. gtest的安装与使用4.1 gtest的介绍4.2 gtest的安装4.3 gtest的使用 5 Spdlog日志组件的安装与使用5.1 Spdlog的介绍5.2 Spdlog的安…...

《Spring 依赖注入方式全解析》

一、Spring 依赖注入概述 Spring 依赖注入&#xff08;Dependency Injection&#xff0c;DI&#xff09;是一种重要的设计模式&#xff0c;它在 Spring 框架中扮演着关键角色。依赖注入的核心概念是将对象所需的依赖关系由外部容器&#xff08;通常是 Spring 容器&#xff09;进…...

【C++动态规划】1411. 给 N x 3 网格图涂色的方案数|1844

本文涉及知识点 C动态规划 LeetCode1411. 给 N x 3 网格图涂色的方案数 提示 你有一个 n x 3 的网格图 grid &#xff0c;你需要用 红&#xff0c;黄&#xff0c;绿 三种颜色之一给每一个格子上色&#xff0c;且确保相邻格子颜色不同&#xff08;也就是有相同水平边或者垂直…...

外包干了3年,技术退步明显...

先说情况&#xff0c;大专毕业&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近6年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落&#xff01; 而我已经在一个企业干了四年的功能…...

SpringBoot 2.x 整合 Redis

整合 1&#xff09;添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- 如果没有使用下面给出的工具类&#xff0c;那么就不需要引入 -…...

React的API✅

createContext createContext要和useContext配合使用&#xff0c;可以理解为 “React自带的redux或mobx” &#xff0c;事实上redux就是用context来实现的。但是一番操作下来我还是感觉&#xff0c;简单的context对视图的更新的细粒度把控比不上mobx&#xff0c;除非配合memo等…...

什么是全渠道客服中心?都包括哪些电商平台?

什么是全渠道客服中心&#xff1f;都包括哪些电商平台&#xff1f; 作者&#xff1a;开源呼叫中心系统 FreeIPCC&#xff0c;Github地址&#xff1a;https://github.com/lihaiya/freeipcc 全渠道客服中心是一种能够同时接入并处理来自多个渠道客户咨询和请求的综合服务平台。以…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

C++ 设计模式 《小明的奶茶加料风波》

&#x1f468;‍&#x1f393; 模式名称&#xff1a;装饰器模式&#xff08;Decorator Pattern&#xff09; &#x1f466; 小明最近上线了校园奶茶配送功能&#xff0c;业务火爆&#xff0c;大家都在加料&#xff1a; 有的同学要加波霸 &#x1f7e4;&#xff0c;有的要加椰果…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

Vue 模板语句的数据来源

&#x1f9e9; Vue 模板语句的数据来源&#xff1a;全方位解析 Vue 模板&#xff08;<template> 部分&#xff09;中的表达式、指令绑定&#xff08;如 v-bind, v-on&#xff09;和插值&#xff08;{{ }}&#xff09;都在一个特定的作用域内求值。这个作用域由当前 组件…...

SpringAI实战:ChatModel智能对话全解

一、引言&#xff1a;Spring AI 与 Chat Model 的核心价值 &#x1f680; 在 Java 生态中集成大模型能力&#xff0c;Spring AI 提供了高效的解决方案 &#x1f916;。其中 Chat Model 作为核心交互组件&#xff0c;通过标准化接口简化了与大语言模型&#xff08;LLM&#xff0…...