Binary Tree二叉树笔记⑤--后序篇
前言在上一篇我们学习了用js解决二叉树的序列化和反序列化的问题,其实序列化的过程就是考察二叉树遍历的过程,反序列化的过程就是考察了二叉树的构造过程,结合了前几章的知识。本篇文章深入学习二叉树后序的妙用,带你了解以下题目:
Leetcode652.寻找重复的子树
寻找重复的子树
这道题实际上就是找子树的问题,看下图
首先节点4可以作为一颗子树,二叉树中有多个节点4
类似的还存在两颗以2为根的重复子树
那么我们返回的list就应该有两个treenode,2和4
具体这道题要怎么做呢?先思考对于一个节点他应该做什么?
我们拿这个2节点作为例子,他是不是重复的子树,是不是就要先知道自己是一颗怎么样的子树,再去找别的子树进行对比?
那么我们解题的关键就来了:
先知道自己长什么样
去看看别人有没有和自己一样的
那么对于第一个问题,根据本文你可以知道我们要用后序遍历的操作去做,其实前序中序都可以,只不过后序在这个阶段看的东西更明显,怎么知道自己是谁呢?其实就是自身加左右子树1234567const postoreder = (n)=>{ if(!n)return null; ...
Binary Tree二叉树笔记④--序列化篇
前言在上一期我们对二叉树的构造进行了深入的了解,重点掌握了构造的核心原理以及一些细节上面的问题。下面来学习二叉树的序列化,通过本篇文章你可以学会以下的题目
Leetcode297.二叉树的序列化与反序列化
二叉树的序列化与反序列化
该题目本质上,就是把二叉树转换为字符串,再从字符串转为二叉树的过程。
至于我们序列化的过程,使用什么符号定义并不重要,只要最后能够反序列化出来即可。
eg
对于一颗这样的树,我们可以将他序列化成2,1,#,6,3,#,#其实他考察的就是如何对二叉树进行遍历。
二叉树的递归遍历有三种,前序中序后序,迭代遍历有层序,那么就从层序开始,看如何解题
前序遍历解法我们知道,前序遍历的代码就是在递归之前写的,那么就有以下的逻辑123if(!root)return '#';traverse(root.left);traverse(root.right);
那么我们就很容易得出序列化的过程了,就是字符串的连接1234var serialize = function (root) { if(!root)return '# ...
Binary Tree二叉树笔记③--构造篇
前言在上一篇笔记里面,我们深入了解了前序和后序遍历的本质,学会了翻转二叉树,将二叉树转为链表和填充二叉树右侧指针三道问题。接下来进一步学习,在本篇能理解并运用以下题目:
Leetcode654.最大二叉树105.从前序遍历和中序遍历构造二叉树106.从中序和后序遍历构造二叉树889.根据前序和后序遍历构造二叉树
最大二叉树
我们细分这道题,其实他在做这样的事情12345678var constructMaximumBinaryTree = function ([3,2,1,6,0,5]) { // 找到数组的最大值 const root = new TreeNode(6) // 递归调用构造左右子树 root.left = constructMaximumBinaryTree([3,2,1]); root.right = constructMaximumBinaryTree([0,5]); return root;}
再详细一点就是如下的思路:1234567891011121314151617181920212223242526 ...
Binary Tree二叉树笔记②--思路篇
前言在上一篇手把手二叉树的笔记中,我们解决了三道问题,二叉树最大深度,二叉树最大直径,和层序遍历。而读完本文,你可以解决以下问题:
Leetcode226.翻转二叉树114.将二叉树展开为链表116.填充二叉树节点的右侧指针
再谈二叉树的重要性对于经典的算法快速排序和归并排序来说,如果你知道二叉树的前序遍历就是快速排序,后序遍历就是归并排序,那么你对二叉树就有比较深入的了解了。
快速排序的逻辑是先找到一个基准点,根据这个基准点,去对我们左侧的数据划分,使得左侧的数据都小于这个基准点,右侧的数据都大于这个基准点,然后在左侧和右侧进行递归这个过程,最后的数组就是被排序的
代码逻辑过程:1234567const quickSort = (arr,i,j)=>{ let p = Math.floor(arr.length/2); ... quickSort(arr,i,p-1); quickSort(arr,p+1,j); ...}
先构造分界点,再根据左右子数组去构造分界点,这不就是二叉树的前序遍历吗
再谈谈归并排序的逻辑,先分割数组 ...
Binary Tree二叉树笔记①--纲领篇
前言labuladong的二叉树算法入门第一章,这段时间的算法确实没什么长进,只停留在会做针对性的题目的阶段,如果出现了变体就很难解决了,所以下决心从算法基础再开始修炼算法。由于labuladong的代码大多数是c++,本文便修改为js进行学习。
读完本文,你可以解决以下问题:104.二叉树的最大深度543.二叉树的直径102.二叉树的层序遍历
二叉树学习的必要性二叉树是所有高级算法的基础,他涉及了递归,回溯,所以算法入门最好就从二叉树开始。
深入理解前中后序根左右,左根右,左右根…可能很多人在学习数据结构的时候,老师教过这样的判断过程。这三句话对应着二叉树的前中后序,但实际上你真的理解这三种遍历顺序吗
从前序开始看,我们知道,有这样的代码1234if(!root)return;console.log(root);traverse(root.left);traverse(root.right);
其实这个就是一个一次遍历,和遍历数组链表的方式大同小异,而所谓的前序遍历,只不过进入第一个节点就开始遍历,而后序遍历是离开一个节点的时候才开始遍历,中序遍历是在遍历完左子树,即将遍历右子 ...
前端必须知道的浏览器性能指标
前言上周一面腾讯云智的时候,面试官问我这么个问题:“你知道浏览器的首屏时间怎么查看吗?”我回答进入页面到最后一个请求回收所用的时间,然后他又问:具体有什么指标来表明呢?于是就有了下文
浏览器性能指标为了描述web页面的性能,开发人员提供了很多可量化的指标来进行分析。比如TTFB、FP、FCP等。指标之间也是有联系的,其中还有部分指标专门为了描述用户交互体验,比如FP、FCP、FSP、FCI、TTI等。下面就来从用户核心指标开始讲述内容。
核心指标当用户打开一个页面,会经历一个这样的视觉过程:白屏->底图->出现部分内容->首屏内容出现,但图片还在加载中->首屏内容和图片都加载完毕
一般在这个首屏的内容大部分被加载的时候,用户才能开始和页面进行交互等操作,所以如果这段响应的时间很长,就会导致用户的体验很差,下面的几个核心指标描述这些过程的关键变化点,通过它们我们可以来了解用户体验。
LCP 最大内容绘制
FID 第一次交互的延迟
CLS 累计位移偏差
Largest Contentful Paint(LCP)最大内容绘制,用于记录视窗内最大元素的绘制时 ...
从0到1TypeScript
前言TS入门教程,从0到1
TS介绍TS是什么?ts是js的超集,超集指的是他包含了es前面所有版本的内容并有自己的拓展。
TS做到了什么?首先js是弱类型,很多错误在运行的时候才能发现。ts使用了他的静态类型检测机制(后面提及)帮助我们提早发现错误。
TS特点
支持最新的js特性(超集)
静态代码检查(解决弱类型)
有其他后端语言的特性(枚举,泛型,类型转化,命名空间,声明文件…)
静态类型检测为什么会产生这个问题?
js在运行代码的时候,需要我们人为的知道代码的返回值是什么,才能做出响应的操作(执行函数才能知道)。不能在我们书写的过程就立刻给出编译错误的反馈。ts就能在(编译之前)告诉我们
非异常故障ts不仅能告诉我们哪些函数的值错误,还能识别类似于错别字,未调用函数和基本逻辑错误1234const user={ name:'ber'}user.location上面这段代码在js中返回undefined,而在ts中提前告诉你这个变量没有定义不能使用
错别字:告诉你对象上面某个方法拼写错误等
未调用函数:函数没有加括号就使用, ...
前端登陆指南
前言前端登陆的四种方式介绍以及应用
关键词:Cookie/Session、Token、SSO单点登录、OAuth第三方登陆
验证登陆
Cookie/Session
Token
SSO 单点登陆
OAuth第三方登陆
cookie session登陆流程:首次登陆
用户访问a.com/pageA并输入密码登陆
服务器验证密码无误后,会创建Session ID并将其保存起来
服务端响应这个请求,并通过Set-Cookie将Session ID写入Cookie中
再次登陆:
用户访问a.com/pageB自动带上第一次登陆写入的Cookie
服务端对比Cookie中的SessionID和保存在服务端的SessionID是否一致
一致则成功
cookie session存在的问题
服务器需要对接大量的客户端,导致服务器压力大。
如果服务器是一个集群,为了同步登陆态,就需要将SessionID同步到每一台机器上,无形中增加了服务器的维护成本。
由于SessionID存放在Cookie中所以无法避免CSRF攻击
token登陆为了解决cookie+session暴露出来的问题,我们 ...
融会贯通八大排序
前言记录常用排序算法的算法思想和实现,力争基础达标,往后深入的点分开补充~
关键词:常用算法、sort排序、冒泡排序、插入排序、选择排序、快速排序、归并排序、桶排序、希尔排序
sort排序直接使用api就能进行排序,注意的点是:不传参,默认是unicode排序,所以常用来排序字母1234567891011let str = "asbcascacsac";let arr = str.split("");let sortArr = arr.sort();console.log(sortArr)/*[ 'a', 'a', 'a', 'a', 'b', 'c', 'c', 'c', 'c', 's', 's', 's']*/
传参,默认两个参,名字无所谓,这里举例是a和b,看返回值来决定升序降序12 ...
浅谈TCP与UDP
前言web前端常考TCP与UDP的知识解析,力争基础达标,往后深入的点分开补充~
关键词:TCP/UDP、三次握手、四次挥手、流量控制、拥塞控制、TCP粘包
TCP和UDP
tcp是面向链接的 udp是无连接的即发送数据前不需要建立连接
tcp提供可靠的服务,也就是说通过tcp连接发送的数据,无差错,不丢失,不重复,且按序到达,udp尽最大的努力交付,即不保证可靠交付。并且因为tcp可靠,面向连接,不会丢失数据因此适合大数据量的交换
tcp是面向字节流,udp面向报文,并且网络出现拥塞不会使得发送速率降低(因此会产生丢包,对实时的应用比如ip电话和视频会议等)
tcp只能是一对一的,udp支持1对1 1对多
tcp的首部较大为20字节 udp只有8字节
tcp是面向连接的可靠性传输,udp是不可靠的
常见使用场景UDP:
直播
游戏
TCP三次握手建立连接前,客户端和服务端需要通过握手来确认对方
客户端发送SYN同步序列编号请求,进入SYN_SEND状态,等待确认
服务端接收并确认SYN包之后发送SYN+ACK包,进入SYN_RECV状态
客户端接收SYN+ACK包之后, ...