前端面试拼图-数据结构与算法

摘要:总结一些前端算法题,持续更新!

一、数据结构与算法

时间复杂度-程序执行时需要的计算量(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拼接到一起

TypeScript 复制代码
/**
* 旋转数组k步使用pop和unshift
*/
function rotate1(arr: number[], k: number): number[] {
  const length = arr.length
  if (!k || length === 0) return
  const step = Math.abs( k%length)   // abs 取绝对值,k不是数值是返回NaN
  // 时间复杂度o(n^2), 空间复杂度o(1)
  for (let i = 0; i<step; i++) {    // 任何值与NaN做计算返回false
    const 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.length
  if (!k || length === 0) return
  const 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数组区别

栈:逻辑结构;理论模型,不管如何实现,不受任何语言限制

数组:物理结构;真实功能实现,受限于编程语言

TypeScript 复制代码
/**
* 判断是否括号匹配
*/
function matchBracket(str: string): boolean {
  const length = str.length
  if(length === 0) return true
  
  const 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 true
  if (left === '[' && right === ']') return true
  if (left === '(' && right === ')') return true
  return false
}

时间复杂度O(n); 空间复杂度O(n)。

相关推荐
莫空0000几秒前
深入理解JavaScript属性描述符:从数据属性到存取器属性
前端·面试
guojl1 分钟前
深度剖析Kafka读写机制
前端
FogLetter2 分钟前
图片懒加载:让网页飞起来的魔法技巧 ✨
前端·javascript·css
Mxuan2 分钟前
vscode webview 插件开发(精装篇)
前端
Mxuan3 分钟前
vscode webview 插件开发(交付篇)
前端
Mxuan5 分钟前
vscode 插件与 electron 应用跳转网页进行登录的实践
前端
拾光拾趣录5 分钟前
JavaScript 加载对浏览器渲染的影响
前端·javascript·浏览器
Codebee5 分钟前
OneCode图表配置速查手册
大数据·前端·数据可视化
然我6 分钟前
React 开发通关指南:用 HTML 的思维写 JS🚀🚀
前端·react.js·html
Mxuan7 分钟前
vscode webview 插件开发(毛坯篇)
前端