【数据结构前置知识】初识集合框架和时间,空间复杂度

2023-11-10

1. 什么是集合框架

Java 集合框架 Java Collection Framework ,又被称为容器 container ,是定义在 java.util 包下的一组接口 interfaces和其实现类 classes
其主要表现为将多个元素 element 置于一个单元中,用于对这些元素进行快速、便捷的存储 store 、检索 retrieve 、管理 manipulate ,即平时我们俗称的增删查改 CRUD 。
例如,一副扑克牌(一组牌的集合)、一个邮箱(一组邮件的集合)、一个通讯录(一组姓名和电话的映射关系)等等。

类和接口总览
在这里插入图片描述

2. 集合框架的重要性

1. 开发中的使用

使用成熟的集合框架,有助于我们便捷、快速的写出高效、稳定的代码

学习背后的数据结构知识,有助于我们理解各个集合的优缺点及使用场景

2. 笔试及面试题
腾讯-Java后台开发面经

  1. HashMap 了解不,介绍一下,如果一个对象为 key 时,hashCode 和 equals 方法的用法要注意什么?
  2. HashSet 和 HashMap 的区别是什么?
  3. HashMap 是线程安全的么?那需要线程安全需要用到什么? 阿里巴巴-Java后台开发面经
  4. ArrayList 和 LinkedList 的区别是什么?
  5. 有了解过 HashMap 的具体实现么?
  6. HashMap 和 ConcurrentHashMap 哪个效率更高? 今日头条-Java后台开发面经
  7. 编程题:判断一个链表是否是一个回文链表。
  8. Redis 的 zset 类型对应到 java 语言中大致是什么类型?
  9. hashCode 主要是用来做什么用的?

3. 背后所涉及的数据结构以及算法

3.1 什么是数据结构

数据结构(Data Structure)是计算机存储组织数据方式,指相互之间存在一种或多种特定关系的数据元素的集合。

3.2 容器背后对应的数据结构

该阶段,我们主要学习以下容器,每个容器其实都是对某种特定数据结构的封装,大概了解一下,后序会给大家详细讲解并模拟实现:

  1. Collection:是一个接口,包含了大部分容器常用的一些方法

  2. List:是一个接口,规范了ArrayList 和 LinkedList中要实现的方法
    2.1ArrayList:实现了List接口,底层为动态类型顺序表
    2.2 LinkedList:实现了List接口,底层为双向链表

  3. Stack:底层是栈,栈是一种特殊的顺序表

  4. Queue:底层是队列,队列是一种特殊的顺序表

  5. Deque:是一个接口

  6. Set:集合,是一个接口,里面放置的是K模型
    6.1HashSet:底层为哈希桶,查询的时间复杂度为O(1)
    6.2TreeSet:底层为红黑树,查询的时间复杂度为O( ),关于key有序的

  7. Map:映射,里面存储的是K-V模型的键值对
    7.1HashMap:底层为哈希桶,查询时间复杂度为O(1)
    7.2TreeMap:底层为红黑树,查询的时间复杂度为O( ),关于key有序

3.3 相关java知识

  1. 泛型 Generic
  2. 自动装箱 autobox 和自动拆箱 autounbox
  3. Object 的 equals 方法
  4. Comparable 和 Comparator 接口

3.4 什么是算法

算法(Algorithm):就是定义良好的计算过程,他取一个或一组的值为输入,并产生出一个或一组值作为输出。简单
来说算法就是一系列的计算步骤,用来将输入数据转化成输出结果。

4.时间复杂度

1. 如何衡量一个算法的好坏

下面求斐波那契数列的算法好还是不好,为什么?该如何衡量一个算法的好坏呢?

public static long Fib(int N){
if(N < 3){
return 1;
}
return Fib(N-1) + Fib(N-2);
}

2. 算法效率

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

3. 时间复杂度

3.1 时间复杂度的概念

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

3.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 执行的基本操作次数
在这里插入图片描述
实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要大概执行次数,那么这里我们使用大O的渐进表示法。
大O符号(Big O notation):是用于描述函数渐进行为的数学符号。

3.3 推导大O阶方法

规则:
1、用常数1取代运行时间中的所有加法常数。
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。
使用大O的渐进表示法以后,Func1的时间复杂度为:
在这里插入图片描述
通过上面我们会发现大O的渐进表示法去掉了那些对结果影响不大的项,简洁明了的表示出了执行次数。
另外有些算法的时间复杂度存在最好、平均和最坏情况:

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

例如:在一个长度为N数组中搜索一个数据x
最好情况:1次找到
最坏情况:N次找到
平均情况:N/2次找到
在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)

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

【实例1】

// 计算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);
}

基本操作执行了2N+10次,通过推导大O阶方法知道,时间复杂度为 O(N)

【实例2】

// 计算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);
}

基本操作执行了M+N次,有两个未知数M和N,时间复杂度为 O(N+M)

【实例3】

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

基本操作执行了100次,通过推导大O阶方法,时间复杂度为 O(1)

【实例4】

// 计算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;
}
}
}

基本操作执行最好N次,最坏执行了(N*(N-1))/2次,通过推导大O阶方法+时间复杂度一般看最坏,时间
复杂度为 O(N^2)

【实例5】

// 计算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;
}

基本操作执行最好1次,最坏 次,时间复杂度为 O( ) ps: 在算法分析中表示是底数
为2,对数为N,有些地方会写成lgN。(建议通过折纸查找的方式讲解logN是怎么计算出来的)(因为二分查
找每次排除掉一半的不适合值,一次二分剩下:n/2
两次二分剩下:n/2/2 = n/4)

【实例6】

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

通过计算分析发现基本操作递归了N次,时间复杂度为O(N)

【实例7】

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

通过计算分析发现基本操作递归了在这里插入图片描述
次,时间复杂度为O( )。(建议画图递归栈帧的二叉树讲解)

5.空间复杂度

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度 。空间复杂度不是程序占用了多少bytes的空
间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计算规则基本跟时间复杂度类似,也使用大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;
}

【实例2】

// 计算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;
}

【实例3】

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

【实例答案及分析】

  1. 实例1使用了常数个额外空间,所以空间复杂度为 O(1)
  2. 实例2动态开辟了N个空间,空间复杂度为 O(N)
  3. 实例3递归调用了N次,开辟了N个栈帧,每个栈帧使用了常数个空间。空间复杂度为O(N)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【数据结构前置知识】初识集合框架和时间,空间复杂度 的相关文章

  • elasticsearch中index.highlight.max_analyzed_offset设置

    elasticsearch中设置index highlight max analyzed offset Caused by java lang IllegalArgumentException The length of message f
  • Dynamics CRM2016详细安装教程-3(Dynamics CRM安装)

    1 以具有管理员级别特权的用户身份登录到将安装 Microsoft Dynamics CRM Server 2016 的域 并且该用户是本地计算机上 Administrators 组的成员 不能以受信任域中成员的身份安装此应用程序 2 双击
  • mysql数据库死锁的产生原因及解决办法

    这篇文章主要介绍了mysql数据库锁的产生原因及解决办法 需要的朋友可以参考下 数据库和操作系统一样 是一个多用户使用的共享资源 当多个用户并发地存取数据 时 在数据库中就会产生多个事务同时存取同一数据的情况 若对并发操作不加控制就可能会读

随机推荐

  • Python+Tensorflow学习(二)——初试keras

    Python Tensorflow学习 二 初试keras 学习视频链接 强推 TensorFlow官方入门实操课程 源码如下 coding utf 8 Time 2021 8 9 10 27 Author 西兰花 File tf01 py
  • 大数据中Linux命令使用的相关操作

    一 常见Linux命令使用 1 cd命令 切换目录 切换到目录 usr local 2 去到目前的上层目录 3 回到自己的主文件夹 ls命令 查看文件与目录 4 查看目录 usr下所有的文件 mkdir命令 新建新目录 5 进入 tmp目录
  • 模块和库的区别

    在编程领域 模块 module 和 库 library 是两个相关但不完全相同的概念 模块 Module 模块是一种组织和封装代码的方式 它是一个包含函数 类 变量等定义的文件 一个模块可以看作是一个独立的单元 它将相关的代码组织在一起 方
  • Xshell连接kali&不成功解决方法

    本文为学习笔记 仅限学习交流 不得利用 从事危害国家或人民安全 荣誉和利益等活动 请参阅 中华人民共和国网络安全法 第一部分 连接 Xshell 官网下载地址 http www netsarang com zh xshell 一 开启Xsh
  • python基础编程小实例2——绝对温标

    编程语言 python3 9 题目 绝对温标的单位为开尔文 简称开 符号为K 绝对温标的零度对应我们日常使用的摄氏温度 单位为摄氏度 简称度 符号为 的 273 15 要求编写代码 实现将用户输入的摄氏温度转换为移绝对温标标识的开氏温度的功
  • Java中String与String的相等判断要用equals

    如题 正确语句 i字符串1 equals 字符串2 错误语句 字符串1 字符串2 在Java中用 比对两个字符串比对的是两个数据的地址值 用equals 比较的才是他们的内容值
  • Python 100 天从新手到大师

    早上好 骚年 我是小菜 我的公众号 菜鸟翻身 会推荐 GitHub 上有用的项目 一分钟 get 一个优秀的开源项目 挖掘开源的价值 我的引语 今天推荐是一个 Python 基础教程 按照教程学习 不出意外 100 天从新手到大师 当下 P
  • disable path和false path的作用与区别

    disable path和false path的作用与区别C 欢迎使用Markdown编辑器 链接 disable与false的相同与不同 false path 指定某一条path 工具计算delay 但不报时序 disable path
  • Java环境变量的配置

    最近有朋友问到环境变量的配置 下面以Windows10系统为例进行Java环境变量配置说明 1 右键点击 此电脑 选择 属性 项 2 点击 高级系统设置 在弹出的系统属性框中 选择 高级 选项卡 默认即显示该选项卡 点击 环境变量 3 在弹
  • 回答问题:你认为AGI应该采用什么思路?

    我是研究AGI基础理论的 我认为AGI要突破首先要对智能的原理有突破 需要建立一套体系描述和解释智能 我认为目前的数学体系有很大的不足 限制了人类对智能的理解 所以需要改革 重新理解一些基础的东西 例如 空间的本质 计算的本质 我认为AGI
  • C++Opencv图像对象Mat的创建和赋值

    Mat中元素的类型以及矩阵的通道个数 它是一系列的预定义的常量 其命名规则为CV 位数 数据类型 通道数 因此在学习图像创建之前先了解一下基本的数据类型 S 有符号整型 U 无符号整型 F 浮点型 CV 8U 8位无符号整数 CV 8S 8
  • Windows CE嵌入式导航系统研究(内核相关)

    1 1 嵌入式车载导航系统的软件设计流程 嵌入式车载系统软件主要包括系统内核 驱动程序 应用程序三部分 设计的过程当中 我们采用瀑布模型进行设计 首先制定Windows CE5 0系统内核 再次编写相关设备驱动 最后编写或移植应用程序 制定
  • 软件测试实验二 白盒测试

    一 实验目的 1 掌握等逻辑覆盖测试法 2 掌握基本路径测试法 3 掌握基于Junit的单元测试 二 实验内容 1 为以下判断等级的程序段设计一组测试用例 要求分别满足语句覆盖 判定覆盖 条件覆盖 判断 条件覆盖 条件组合覆盖 public
  • 809协议nodejs编写笔记

    一 总体流程 数据首先通过receiver接受层接收 去掉标识头和标识尾 再进入depacker解包层进行解包 把标识头分解出来并解析 之后发给handler处理层根据不同的消息id选择使用不同的业务逻辑 如果有应答 则通过sender发送
  • 7.12 redis未授权访问漏洞

    在1 txt添加存在redis未授权访问漏洞的IP redis py输入脚本 redis cli exe h IP p 端口号
  • async/await 异步函数

    1 async异步函数的使用 await async写法 async function foo1 const foo2 async gt 2 async异步函数的执行流程 都是同步代码 跟普通函数代码没区别 async function f
  • RTP - 视频流广播

    这是用RTP RFC3350 按RFC2550封装MPEG ES流数据的发送程序 学习RTP的路真的辛苦 在网上收集的有关RTP的程序都是那种只负责RTP数据包发送的库 如jrtplib等 他们的DEMO 程序都只是用来发发字符串 编编聊天
  • mac mongodb Automatically disabling TLS 1.0, to force-enable TLS 1.0 specify --sslDisabledProtocols

    mac 下 mongodb 执行命令 mongod 报错 标题为报错的第一句 因为一般人百度的时候都是根据第一句百度 所以起的这个标题 具体报错如下图 我的具体信息如上 可以发现 报错的主要信息在于 没有找到 data 数据的存放路径导致的
  • 【华为OD统一考试A卷

    在线OJ 已购买本专栏用户 请私信博主开通账号 在线刷题 运行出现 Runtime Error 0Aborted 请忽略 华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一
  • 【数据结构前置知识】初识集合框架和时间,空间复杂度

    文章目录 1 什么是集合框架 2 集合框架的重要性 3 背后所涉及的数据结构以及算法 3 1 什么是数据结构 3 2 容器背后对应的数据结构 3 3 相关java知识 3 4 什么是算法 4 时间复杂度 1 如何衡量一个算法的好坏 2 算法