前端面试拼图-数据结构与算法
摘要:总结一些前端算法题,持续更新!
一、数据结构与算法
时间复杂度-程序执行时需要的计算量(CPU)
空间复杂度-程序执行时需要的内存空间

前端开发:重时间,轻空间
1.把一个数组旋转k步
array = [1, 2, 3, 4, 5, 6, 7] 旋转数组k=3, 结果[5, 6, 7, 1, 2, 3, 4]
思路1:把末尾的元素挨个pop,然后unshift到数组前面;
思路2:把数组拆分,最后concat拼接到一起
/**
* 旋转数组k步使用pop和unshift
*/
function rotate1(arr: number[], k: number): number[] {const length = arr.lengthif (!k || length === 0) returnconst step = Math.abs( k%length) // abs 取绝对值,k不是数值是返回NaN// 时间复杂度o(n^2), 空间复杂度o(1)for (let i = 0; i<step; i++) { // 任何值与NaN做计算返回falseconst n = arr.pop()if (n != null ) {arr.unshift(n) //数组是一个有序结构,unshift操作会非常慢!!!O(n);splice和shift也很慢}}return arr
}
/**
* 旋转数组k步使用concat
*/
function rotate2(arr: number[], k: number): number[] {const length = arr.lengthif (!k || length === 0) returnconst step = Math.abs( k%length) // abs 取绝对值const part1 = arr.slice(-step) // O(1)const part2 = arr.slice(0,length-step)// 时间复杂度o(1), 空间复杂度O(n)return part1.concat(part2)
}
常见内置API中的复杂度:
- unshift: unshift 方法将给定的值插入到类数组对象的开头,并返回新的数组长度。时间复杂度为 O(n),其中 n 是数组的长度,因为在插入时需要将原有的元素逐一往后移动一位;空间复杂度为 O(1)。
- splice: splice 方法用于从数组中添加或删除元素,并返回被删除的元素组成的新数组。splice 的时间复杂度为 O(n),其中 n 是数组的长度,因为在删除或插入元素后,需要移动数组中的其他元素以保持连续性;空间复杂度为 O(n),因为需要创建一个新的数组。
- shift: shift 方法用于从数组的开头删除一个元素,并返回被删除的元素。shift 的时间复杂度为 O(n),其中 n 是数组的长度,因为在删除元素后,需要将数组中的其他元素往前移动一位以保持连续性;空间复杂度为 O(1),因为不需要额外的空间来存储。
- concat: concat 方法用于将两个或多个数组合并成一个新数组。时间复杂度为 O(1),数组末尾操作;空间复杂度为 O(n+m),m、n是原数组长度,因为新的数组需要存储。
- slice: slice 方法用于从数组中提取出指定范围的元素,并返回一个新数组(不改变原数组)。时间复杂度为 O(1);空间复杂度为 O(n),因为需要创建一个新的数组来存储提取的元素。
2.判断字符串是否为括号匹配
一个字符串s可能包括{}()[]三种括号,判断s是否是括号匹配
考察的数据结构是栈,先进后出;ApI: push pop length
栈 VS数组区别
栈:逻辑结构;理论模型,不管如何实现,不受任何语言限制
数组:物理结构;真实功能实现,受限于编程语言
/**
* 判断是否括号匹配
*/
function matchBracket(str: string): boolean {const length = str.lengthif(length === 0) return trueconst stack = []const leftSymbols = '{[('const rightSymbols = '}])'for (let i = 0; i <length; i++) {const s = str[i]if (leftSymbols.includes(s)) {stack.push(s) // 左括号,压栈} else if (rightSymbols.includes(s)) {// 左括号,判断栈顶(是否出栈)const top = stack[stack.length-1]if (isMatch(top, s)) {stack.pop} else {return false}}}return stack.length === 0
}
/**
* 判断左右括号是否匹配
*/
functionn isMatch(left: string, right: string): boolean {if (left === '{' && right === '}') return trueif (left === '[' && right === ']') return trueif (left === '(' && right === ')') return truereturn false
}
时间复杂度O(n); 空间复杂度O(n)
3.定义一个JS函数,反转单向链表
链表
链表是一种物理结构(非逻辑结构), 类似于数组
数组需要一段连续的内存空间,而链表是零散的
链表节点的数据结构{value, next?, prev?}
链表 VS 数组
都是有序结构(Set是无序的)
- 链表:查询需要遍历元素慢O(n), 新增和删除不需要移动其他元素很快快O(1);
- 数组:按照索引查询快时间复杂度O(1), 新增和删除需要移动其他元素比较慢慢O(n);
- 数组适合随机访问元素、大小固定的情况,而链表适合频繁的插入或删除操作、大小不确定的情况
/**
* 反转单项链表
*/
interface ILinkListNode { // 定义类型value: number // 类型结构,value、next?next?: ILinkListNode //?表示next是可选的
}/**
* 反转单向链表,并返回反转之后的head node
*/
fucntion reserveLinkList(listNode: ILinkListNode): ILinkListNode {// 定义三个指针let prevNode: ILinkListNode | undefined = undefinedlet curNode: ILinkListNode | undefined = undefinedlet nextNode: ILinkListNode | undefined = listNode// 以nextNode为主,遍历链表while(nextNode) {// 第一个元素,删掉next,防止循环引用if (curNode && !prevNode) {delete curNode.next}// 反转指针if (curNode && prevNode) { 中间状态,指针都有值curNode.next = prevNode}// 指针后移prevNode = curNodecurNode = nextNodenextNode = nextNode?.next //有nextNode.next则返回,否则返回空 } // 最后一个元素:当nextNode空时, 此时curNode尚未设置nextcurNode!.next = prevNodereturn curNode!
}/**
* 根据数组创建单项链表
*/
function createLinkList(arr: number): ILinkListNode {const length = arr.lengthif (length === 0) throw new Error('array is Empty')let curNode: ILinkListNode = {value: arr[length-1]}if (length == 1) return curNodefor ( let i = length-2; i >=0; i--) {curNode = {curNode = {value: arr[i],next: curNode}}}reurn curNode
}
链表在前端应用不多,例如React Fiber使用链表,通过将渲染树转换成链表表示,更灵活地控制渲染:
在 React 16 中引入的 Fiber 架构使用链表数据结构来表示组件树,这样可以更好地控制组件树的遍历和更新过程。每个 Fiber 节点都包含了对应组件的信息以及与其他 Fiber 节点的关联关系,通过链表将这些 Fiber 节点连接起来形成一个虚拟的组件树。这种链表的结构使得 React 能够更灵活地控制组件更新的顺序,实现异步渲染和优先级调度等特性。
使用链表而不是传统的递归方式遍历组件树,使得 React 能够实现更细粒度的控制,例如中断和恢复更新过程、优先级调度等。这种设计可以提高 React 应用的响应速度和用户体验,并且更好地支持 Suspense 和并发模式等新特性的引入。

4. 链表和数组,那个实现队列更快?
数组是连续存储,push很快,shift很慢
链表是非连续存储,add和delete都很快(但查找很慢)
结论:链表实现队列更快
链表实现队列
- 单向链表,但要同时记录head和tail
- 要从tail入队,从head出队,否则出队时tail不好定位
- length要实时记录,不可遍历链表获取(慢)
/**
* 用链表实现队列
*/
interface IListNode {value: numbernext: IListNode | null
}
class MyQueue {private head: IListNode | null = nullprivate tail: IListNode | null = nullprivate len = 0/*** 入队,在tail位置*/add(n: number) {const newNode: IListNode = {value: n,next: null, // tail入队,结尾节点没next}// 处理headif (this.head == null) {this.head = newNode}// 处理tailconst tailNode = this.tailif (tailNode) {tailNode.next = nextNode}this.tail = newNodethis.len++}/*** 出队,在head的位置*/delete(): number | null {const headNode = this.headif (headNode = null) return nullif (this.len <= 0) return null// 取值const value = headNode.value// 处理headthis.head = headNode.next// 记录长度len--return value}get length(): number {return this.len // length要单独存储,不能遍历链表来获取}
}
链表和数组实现队列的性能对比
- 空间复杂度都是O(n)
- add时间复杂度:链表O(1),数组O(1);
- delete时间复杂度:链表O(1),数组O(n)
数据结构的选择,要比算法优化更重要
相关文章:
前端面试拼图-数据结构与算法
摘要:总结一些前端算法题,持续更新! 一、数据结构与算法 时间复杂度-程序执行时需要的计算量(CPU) 空间复杂度-程序执行时需要的内存空间 前端开发:重时间,轻空间 1.把一个数组旋转k步 arr…...
在C++的union中使用std::string(非POD对象)的陷阱
struct和union的对比 union最开始是C语言中的关键字,在嵌入式中比较常见,由于嵌入式内存比较稀缺,所以常用union用来节约空间,在其他需要节省内存的地方也可以用到这个关键字,写一个简单程序来说明union的用途 struc…...
Spring Cloud Netflix Eureka的参数调优
下面主要分为Client端和Server端两大类进行简述,Eureka的几个核心参数 客户端参数 Client端的核心参数 参数默认值说明eureka.client.availability-zones告知Client有哪些region以及availability-zones,支持配置修改运行时生效eureka.client.filter-o…...
Wireshark不显示Thrift协议
使用Wireshark对thrift协议进行抓包,但是只显示了传输层的tcp协议: "右键" -> "Decode As" 选择thrift的tcp端口 将“当前”修改为Thrift,然后点击“确定” 设置后,可以发现Wireshark里面显示的协议从Tcp变…...
VMware虚拟机安装openEuler系统(一)(2024)
目录 一、下载ISO镜像 二、开始创建虚拟机 通过实践是学习openEuler开源Linux系统的最佳方式。因此我们首先得搭建一个openEuler实战环境,文章是在Windows系统上使用VMware Workstation虚拟化软件,安装和学习openEuler开源Linux操作系统。 使用虚拟机…...
Rust入门
文章目录 一、HelloWorld二、控制台输入 以最简单的两个Rust程序例子入门Rust。首先需要下载安装Rust,之后在VSCode或Clion中运行Rust需要下载Rust插件 一、HelloWorld fn main(){println!("Hello World!"); }二、控制台输入 use std::io::stdin; fn …...
RabiitMQ延迟队列(死信交换机)
Dead Letter Exchange(死信交换机) 在MQ中,当消息成为死信(Dead message 死掉的信息)后,消息中间件可以将其从当前队列发送到另一个队列中,这个队列就是死信队列。而 在RabbitMQ中,由…...
浅谈应该遵守的伦敦银交易规则
做伦敦银投资的朋友应遵守伦敦银交易规则,伦敦银交易规则不是指那些伦敦银交易技巧,而是在这个市场中要遵循的一些约定,下面我们就来讨论一下。 风险管理。风险管理即指投资者控制自己一笔乃至整体交易的风险,没有风险管理意识的投…...
安装opencart
一、安装模板 Install SO Emarket Opencart 4 Theme 一:so_emarket_quick2 二:theme package installation 1、installed opencart Default 2、Extensions->Installer->Upload->so_emarket_theme_oc4011_home21_to_home35_v2.0.3->so_theme…...
Qt PCL学习(一):环境搭建
参考 (QT配置pcl)PCL1.12.1QT5.15.2vs2019cmake3.22.4vtk9.1.0visual studio2019Qt5.15.2PCL1.12.1vtk9.1.0cmake3.22.2 本博客用到的所有资源 版本一览:Visual Studio 2019 Qt 5.15.2 PCL 1.12.1 VTK 9.1.0https://pan.baidu.com/s/1xW7xCdR5QzgS1_d1NeIZpQ?pw…...
代码随想录算法训练营第四十二天 | 416. 分割等和子集
题目链接:416. 分割等和子集 文章讲解:代码随想录 416. 分割等和子集讲解 视频讲解:动态规划之背包问题,这个包能装满吗?| LeetCode:416.分割等和子集 思路和解法 题目: 给你一个 只包含正整…...
Spring GateWay
概述简介 能干什么 反向代理 鉴权 流量控制 熔断 日志监控 Spring Cloud Gateway 与Zuul的区别 在SpringCloud Finchley正式版之前,Spring Cloud推荐的网关是 Netflix提供的Zuul: 1、Zuul 1.x,是一个基于阻塞Ⅳ/O的APl Gateway 2、Zuul 1.x基于Servl…...
介绍一个关于 JSON 可视化的网站
最近在看到一个比较好玩的网站,可以将 JSON以可视化的方式展现出现,比如存在一下JSON数据: {"id": "f3bbc3bc-9f34-4bf7-8a0f-7e6f6e6fbb9a","isActive": false,"age": 25,"name": "…...
系统架构设计师-22年-上午答案
系统架构设计师-22年-上午答案 更多软考资料 https://ruankao.blog.csdn.net/ 1 ~ 10 1 云计算服务体系结构如下图所示,图中①、②、③分别与 SaaS PaaS Iaas相对应,图中①、②、③应为(1) #mermaid-svg-xqMbIVMC8pWrne2L {font-family:"trebuch…...
2024 年改变行业的人工智能主要趋势
1、导读 当我们迈入 2024 年时,了解人工智能趋势至关重要。它们不仅仅涉及技术进步;还涉及技术进步。它们意味着我们解决问题、做出决策和展望未来的方式发生了转变。本文旨在探索这些变革趋势,并强调人工智能如何不断突破可能性的界限&…...
【Linux Day15 TCP网络通讯】
TCP网络通讯 TCP编程流程 接口介绍 socket()方法是用来创建一个套接字,有了套接字就可以通过网络进行数据的收发。创建套接字时要指定使用的服务类型,使用 TCP 协议选择流式服务(SOCK_STREAM)。 **bind()方法是用来指定套接字使…...
力扣:78. 子集
回溯解法思路: 1.跟前面的组合题目有相同的点,主要区别在于:组合题目是遍历到符合条件的组合时加入li1集合中,子集题目是每递归一次就要把结果加入到li1集合中,并遍历但nums数组的最后。其他点和组合问题一样。 clas…...
(29)数组异或操作
文章目录 每日一言题目解题思路方法一方法二 代码方法一方法二 结语 每日一言 泉涸,鱼相与处于陆,相呴以湿,相濡以沫,不如相忘于江湖。 --庄子内篇大宗师 题目 题目链接:数组异或操作 给你两个整数,n 和…...
mac检查CPU温度和风扇速度软件:Macs Fan Control Pro 1.5.17中文版
Macs Fan Control Pro for Mac是一款专业的电脑风扇控制工具,旨在帮助Mac用户有效控制电脑的风扇速度,提高电脑的运行效率和稳定性。 软件下载:Macs Fan Control Pro 1.5.17中文版 该软件支持多种风扇控制模式和预设方案,用户可以…...
数据结构——单链表详解
目录 前言 一.什么是链表 1.概念 编辑 2.分类 二.单链表的实现(不带头单向不循环链表) 2.1初始化 2.2打印 2.3创建新节点 2.4头插、尾插 2.5头删、尾删 2.6查找 2.7在指定位置之前插入 2.8在指定位置之后插入 2.9删除pos位置 2.10删除pos之后的 2.11销毁链表…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...
《Docker》架构
文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器,docker,镜像,k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...
