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

摘要:最近,看了下慕课2周刷完n道面试题,记录下...

1. 求一个二叉搜索树的第k小值

        二叉树(Binary Tree)

        是一棵树

        每个节点最多两个子节点

        树节点的数据结构{value, left?, right?}

        二叉树的遍历

        前序遍历:root→left→right

        中序遍历:left→root→right

        后序遍历:left→right→root

        二叉搜索树BST(Binary Search Tree)

        left(包括其后代) value ≤ root value

        right (包括其后代) value ≥ root value

        可使用二分法进行快速查找

        解题思路:BST中序遍历,从小到大的排序

                          找到排序后的第k个值

/**
* 二叉搜索树
*/
interface ITreeNode {value: numberleft: ITreeNode | nullright: ITreeNode | null
}const arr: number[] = []/**
* 二叉树前序遍历
*/
function preOrderTraverse(node: ITreeNode | null) {if ( node == null) return//console.log(node.value)arr.push(node.value)preOrderTraverse(node.left)preOrderTraverse(node.right)
}/**
* 二叉树中序遍历
*/
function inOrderTraverse(node: ITreeNode | null) {if ( node == null) returninOrderTraverse(node.left)// console.log(node.value)arr.push(node.value)inOrderTraverse(node.right)
}/**
* 二叉树后序遍历
*/
function postOrderTraverse(node: ITreeNode | null) {if ( node == null) returnpostOrderTraverse(node.left)postOrderTraverse(node.right)// console.log(node.value)arr.push(node.value)
}/**
* **寻找BST中的第k小值**
*/
function getKthValue(node: ITreeNode, k: number): number | null {inOrderTraverse(node)console.log(arr)return arr[k-1] || null
}const bst: ITreeNode = {value: 5,left: {value: 3,left: {value: 2,left: null,right: null},right: {value: 4,left: null,right: null}},right: {value: 7,left: {value: 6,left: null,right: null},right: {value: 8,left: null,right: null}}
}//preOrderTraverse(tree)

平衡二叉树 | HZFE - 剑指前端 Offer题目描述icon-default.png?t=N7T8https://febook.hzfe.org/awesome-interview/book1/algorithm-balanced-binary-trees        扩展:为何二叉树如此重要,而不是三叉树、四叉树?

        性能、性能、还是性能!重要的事情说三遍

        数组:查找快O(1),增删慢O(n);链表:查找慢O(n),增删快O(1)

        二叉搜索树BST:查找快、增删快—"木桶效应"

        平衡二叉树

        BST如果不平衡,那就又成了链表

        所以要尽量平衡:平衡二叉搜索树BBST(其增删查,时间复杂度都是O(logn),即树的高度)

        红黑树:本质是一种自平衡二叉树

        分为红/黑两种颜色,通过颜色转换来维持输的平衡

        相对于普通平衡二叉树,它维持平衡的效率更高

        B树

        物理上是多叉树,但逻辑上是二叉树

        一般用于高效I/O, 关系型数据库常用B树 来组织数据

        扩展2:堆有什么特点?和二叉树又什么关系?

        堆栈模型

        JS执行时,值类型变量,存储在栈中;引用类型变量,存储在堆中

        堆是完全二叉树

        最大堆:父节点 ≥子节点

        最小堆:父节点≤子节点

        满二叉树(又叫完美二叉树):所有层的节点都被填满;

        完全二叉树:最底层节点靠左填充,其它层节点全被填满

7.1   二叉树 - Hello 算法动画图解、一键运行的数据结构与算法教程icon-default.png?t=N7T8https://www.hello-algo.com/chapter_tree/binary_tree/#1_1        逻辑结构 VS 物理结构

        堆:逻辑结构是一颗二叉树,但它的物理结构式一个数组

        堆的使用场景

        特别适合"堆栈模型"

        堆的数据,都是在栈中引用的,不需要从root遍历

        堆恰巧是数组形式,根据栈的地址,可用O(1)找到目标

2. JS计算斐波那契数列的第n个值

/**
* 斐波那契额数列(递归)
*/
function fibonacci(n:number): number{if(n <=1 ) return nreturn fibonacci(n-1) + fibonacci(n-2)
}

        递归有大量重复计算,其时间复杂度是O(2^n)

        优化:不用递归用循环,记录中间结果,时间复杂度O(n)

/**
* 斐波那契额数列(循环)
*/
function fibonacci(n:number): number{if(n <=1 ) return nlet n1 = 1  //记录n-1的结果let n2 = 0  //记录n-2的结果let res = 0for(let i = 2; i <= n; i++) {res = n1 + n2;// 记录中间结果n2 = n1n1 = res} return res
}

        动态规划:

        把一个大问题,拆解为一个小问题,逐级向下拆解

        用递归的思想去分析问题,再改用循环来实现

        算法三大思维:贪心、二分、动态规划

        扩展:青蛙跳台阶问题,一只青蛙,一次可跳1级,也可跳两级,请问青蛙跳到n级台阶,总共有多少种方式?

        第一次跳1级则有f(n-1)种方式,跳2级则有f(n-2)种方式,则结果和斐波那契额数列一样。

3. 将数组的0 移动到末尾

        如输入[1,0,3,0,11,0],输出[1,3,11,0,0,0],只移动0,其他顺序不变;必须在原数组进行操作

        传统思路

        遍历数组,遇到0则push到数组末尾

        用splice截取当前元素

        时间复杂度O(n^2)—算法不可用

        数组是连续存储,要慎用splice unshift 等API

/**
* 移动0到数组末尾(嵌套循环)
*/
function moveZero1(arr:number[]):void {const length = arr.lengthif(length === 0) returnlet zeroLength = 0// **O(n^2)**for (let i = 0; i < length - zeroLength; i++) {if (arr[i] === 0) {arr.push(0)arr.splice(i,1)  // 本身就有O(n)i-- //数组接去了一个元素,i要递减,否则连续0就会有错误zeroLength++ // 累加0的长度}}
}

        双指针思路(解决嵌套循环的有效)

        定义j指向第一个0,i指向j后面的第一个非0

        交换i和j的值,继续向后移动

        只遍历一次,所以时间复杂度是O(n)

/**
* 移动0到数组末尾(双指针)
*/
function moveZero2(arr:number[]):void {const length = arr.lengthif(length === 0) returnlet ilet j = -1 // 指向第一个0for(i=0; i < length; i++) {if(arr[i] === 0) {if (j < 0) {   // 第一个0j = i}}if(arr[i] !== 0 && j >=0 ) {const n = arr[i]arr[i] = arr[j]arr[j] = nj++}}
}

4. 获取字符串中连续最多的字符,以及次数

        如输入'abbcccddeeee1234',计算得到连输最多的字符是'e',为4次

        传统思路

        嵌套循环,找出每个字符的连续次数,并记录

        看似时间复杂度是O(n^2)

        但实际时间复杂度是多少?—O(n),因为有'跳步'

/**
* 求连续最多的字符和次数(嵌套循环)
*/
interface IRes {char: stringlength: number
}
function findContinuousChars1(str:string):IRes {const res:IRes = {char: '',length: 0}const length = str.lengthif (length === 0) return reslet tempLength = 0 //临时记录当前连续字符串的长度// 时间复杂度O(n)for(let i = 0; i < length; i++) {tempLength = 0 // 重置for(let j = i; j < length; j++) {if (str[i] === str[j]) {tempLength++}if(str[i] !== str[j] || j === length-1) {// 不相等,或者已经到最后一个元素。要去判断最大值if (tempLength > res.length) {res.char = str[i]res.length = tempLength}if (i < length - 1) {i = j -1   // 跳步}break}}}  return res
}

        双指针思路(适用于解决嵌套循环类问题)

        定义指针i和j;j不动,i继续移动

        如果i和j的值一直相等,则i继续移动

        直到i和j的值不相等,记录处理,让j追上i。继续第一步

/**
* 求连续最多的字符和次数(双指针)
*/
interface IRes {char: stringlength: number
}
function findContinuousChars2(str:string):IRes {const res:IRes = {char: '',length: 0}const length = str.lengthif (length === 0) return reslet tempLength = 0 //临时记录当前连续字符串的长度// 时间复杂度O(n)let i = 0let j = 0for(; i < length; i++) {if(str[i] === str[j]) {tempLength++}if(str[i] !== str[j] || i === length-1) {// 不相等,或者i到了字符串的末尾if(tempLength > res.length) {res.char = str[j]res.length = tempLength}tempLength = 0  //重置长度if(i < length - 1) {j = i //让j"追上" ii--}}}return res
}

ps:算法题尽量使用低级的代码,慎用语法糖或者高级API

5. 用JS实现快速排序,并说明时间复杂度

6. 获取1-10000之前所有的对称数

7. 如何实现高效的英文单词前缀匹配

未完待续……

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

视觉轮速滤波融合1讲:理论推导

视觉轮速滤波融合理论推导 文章目录 视觉轮速滤波融合理论推导1 坐标系2 轮速计2.1 运动学模型2.2 外参 3 状态和协方差矩阵3.1 状态3.2 协方差矩阵 4 Wheel Propagation4.1 连续运动学4.2 离散积分4.2.1 状态均值递推4.2.2 协方差递推 5 Visual update5.1 视觉残差与雅可比5.2…

【C语言】【Leetcode】70. 爬楼梯

文章目录 题目思路&#xff1a;简单递归 > 动态规划 题目 链接: link 思路&#xff1a;简单递归 > 动态规划 这题类似于斐波那契数列的算法&#xff0c;结果其实就是到达前一步和到达前两步的方法之和&#xff0c;一直递归到n1和n2时就行了&#xff0c;但是这种算法有个…

今天聊聊Docker

在数字化时代&#xff0c;软件应用的开发和部署变得越来越复杂。环境配置、依赖管理、版本控制等问题给开发者带来了不小的挑战。而Docker作为一种容器化技术&#xff0c;正以其独特的优势成为解决这些问题的利器。本文将介绍Docker的基本概念、优势以及应用场景&#xff0c;帮…

C++基础之继承续(十六)

一.基类与派生类之间的转换 可以把派生类赋值给基类可以把基类引用绑定派生类对象可以把基类指针指向派生类对象 #include <iostream>using std::cin; using std::cout; using std::endl;//基类与派生类相互转化 class Base { private:int _x; public:Base(int x0):_x(…

Amuse .NET application for stable diffusion

Amuse github地址&#xff1a;https://github.com/tianleiwu/Amuse .NET application for stable diffusion, Leveraging OnnxStack, Amuse seamlessly integrates many StableDiffusion capabilities all within the .NET eco-system Welcome to Amuse! Amuse is a profes…

CAPL - 如何实现弹窗提示和弹窗操作(续)

目录 函数介绍 openPanel closePanel 代码示例 1、简单的打开关闭panel面板

自动驾驶-如何进行多传感器的融合

自动驾驶-如何进行多传感器的融合 附赠自动驾驶学习资料和量产经验&#xff1a;链接 引言 自动驾驶中主要使用的感知传感器是摄像头和激光雷达&#xff0c;这两种模态的数据都可以进行目标检测和语义分割并用于自动驾驶中&#xff0c;但是如果只使用单一的传感器进行上述工作…

文献速递:文献速递:基于SAM的医学图像分割--SAM-Med3D

Title 题目 SAM-Med3D 01 文献速递介绍 医学图像分析已成为现代医疗保健不可或缺的基石&#xff0c;辅助诊断、治疗计划和进一步的医学研究]。在这一领域中最重要的挑战之一是精确分割体积医学图像。尽管众多方法在一系列目标上展现了值得称赞的有效性&#xff0c;但现有的…

C/C++ 语言中的 ​if...else if...else 语句

C/C 语言中的 ​if...else if...else 语句 1. if statement2. if...else statement3. if...else if...else statementReferences 1. if statement The syntax of the if statement is: if (condition) {// body of if statement }The code inside { } is the body of the if …

javaScript——BFS结合队列求迷宫最短路径

这里推荐先去看下B站这个老师讲的BFS迷宫问题&#xff0c;只用看前五分钟就能懂用BFS队列实现的原理。[POJ] 3984 迷宫问题 BFS_哔哩哔哩_bilibili 问题描述&#xff1a;由m*n的矩阵构成了一个迷宫&#xff0c; 矩阵中为1的元素表示障碍物&#xff0c;不能走&#xff0c;为0表示…

AcWing 830. 单调栈

解题思路 对于将要入栈的元素来说&#xff0c;在对栈进行更新后&#xff08;即弹出了所有比自己大的元素&#xff09;&#xff0c;此时栈顶元素就是数组中左侧第一个比自己小的元素&#xff1b; 对于将要入栈的元素来说&#xff0c;在对栈进行更新后&#xff08;即弹出了所有比…

【干货】无源滤波器设计讲解,工作原理+设计步骤

今天给大家分享的是&#xff1a;无源模拟滤波器针对很多入门小白不懂滤波器设计&#xff0c;一些老工程师上班很多年有的也不懂得总结知识点&#xff0c;以及想学习不知道怎么系统学习的这一类人群&#xff0c;前方知识点来袭&#xff0c;请君放心食用~ 在信号处理领域&#x…

Git基础(25):Cherry Pick合并指定commit id的提交

文章目录 前言指定commit id合并使用TortoiseGit执行cherry-pick命令 前言 开发中&#xff0c;我们会存在多个分支开发的情况&#xff0c;比如dev&#xff0c;test, prod分支&#xff0c;dev分支在开发新功能&#xff0c;prod作为生产分支已发布。如果某个时候&#xff0c;我们…

基于stm32与TJC3224T124_011串口屏的PID调参器(附完整工程)

电赛在即&#xff0c;每次比赛调PID都是一件比较繁琐的事。每次都要在程序中改完再烧录到板子上&#xff0c;特别耗时。正好最近发现实验室的一块串口屏比较好玩。 于是就做了这个调PID的东西。它可以通过串口直接修改PID的值&#xff0c;从而达到快速调PID的目的。下面我将完整…

论文阅读---VITC----Early Convolutions Help Transformers See Better

论文题目&#xff1a;Early Convolutions Help Transformers See Better 早期的卷积网络帮助transformers性能提升 vit 存在不合格的可优化性&#xff0c;它们对优化器的选择很敏感。相反现代卷积神经网络更容易优化。 vit对优化器的选择[40](AdamW [27] vs. SGD)&#xff0…

CTF题型 nodejs(1) 命令执行绕过典型例题

CTF题型 nodejs(1) 命令执行绕过 文章目录 CTF题型 nodejs(1) 命令执行绕过一.nodejs中的命令执行二.nodejs中的命令绕过1.编码绕过2.拼接绕过3.模板字符串4.Obejct.keys5.反射6.过滤中括号的情况典型例题1.[GFCTF 2021]ez_calc2.[西湖论剑 2022]Node Magical Login 一.nodejs中…

力扣Lc21--- 389. 找不同(java版)-2024年3月26日

1.题目描述 2.知识点 &#xff08;1&#xff09;在这段代码中&#xff1a; // 统计字符串s中每个字符的出现次数for (int i 0; i < s.length(); i) {count[s.charAt(i) - a];}对于字符串s “abcd”&#xff1a; 当 i 0&#xff0c;s.charAt(i) ‘a’&#xff0c;ASCII…

yolov9目标检测可视化图形界面GUI源码

该系统是由微智启软件工作室基于yolov9pyside6开发的目标检测可视化界面系统 运行环境&#xff1a; window python3.8 安装依赖后&#xff0c;运行源码目录下的wzq.py启动 程序提供了ui源文件&#xff0c;可以拖动到Qt编辑器修改样式&#xff0c;然后通过pyside6把ui转成python…

JMeter 如何并发执行 Python 脚本

要在JMeter中并发执行Python脚本&#xff0c;可以使用Jython脚本或通过调用外部Python脚本的方式实现。 使用Jython脚本并发执行Python脚本的步骤&#xff1a; 1、创建一个线程组&#xff1a;在JMeter界面中&#xff0c;右键点击测试计划&#xff0c;选择 “添加” -> “线…

词根词缀基础

一&#xff0e;词根词缀方法&#xff1a; 1. 类似中文的偏旁部首&#xff08;比如“休”单人旁木→一个人靠木头上休息&#xff09; 2. 把单词拆分后&#xff0c;每一个部分都有它自己的意思&#xff0c;拼凑在一起就构成了这个单词的意思 3. 一个规律&#xff0c;适用大部分…