浅聊一下
在这些天的面试中,总结了一些送分的题目...
面试了这么多天,觉得一个人的力量还是太过薄弱,如果你和我一样想进大厂,欢迎掘友们私聊我交流面经(wechat: LongLBond)
深度优先遍历和广度优先遍历
通常在遍历一棵树的时候,我们会遇到DFS和BFS
DFS
DFS深度优先,我们很容易理解就是要先遍历到树的每个结点的最深处
js
function dfs(node){
console.log(node.value)
for(let child of node){
dfs(child)
}
}
-
打印当前节点的值
-
遍历当前节点的每个子节点:
-
for(let child of node)
:这里使用了for...of
语法来遍历当前节点的每个子节点。 -
对于每个子节点,会递归调用
dfs(child)
函数:- 这样会先处理当前子节点,打印其值,然后继续深度优先搜索子节点的子节点,直到整个树结构被完全探索。
-
BFS
BFS广度优先遍历,按层级遍历,要实现层级遍历使用队列是再好不过的了...
js
function bfs(root){
let queue = [root]
while(queue.length){
const currentNode = queue.shift()
console.log(currentNode.value)
if(currentNode.children){
currentNode.children.forEach(child=>{
queue.push(child)
})
}
}
}
- 首先维护一个队列,遍历队列,队列为空代表树已经遍历完成
- 根据队列先进先出,取出一个结点,打印值,并且将子结点依次存入队列
- 循环...
将列表组装成树形结构
这道题目考察的是一个开发能力
应用场景: 省县市选择、多级菜单
在前后端的数据流转时,后端返回的数据是一条一条的,使用select*
获取数据,而这些数据的父子关系在返回数据的时候并没有提现,所以就需要我们进行一个列表组装成树形结构的操作...
数据:
js
[
{
id: 1001,
parentId: 0,
name: "AA",
},
{
id: 1002,
parentId: 1001,
name: "BB",
},
{
id: 1003,
parentId: 1001,
name: "CC",
},
{
id: 1004,
parentId: 1003,
name: "DD",
},
{
id: 1005,
parentId: 1003,
name: "EE",
},
{
id: 1006,
parentId: 1002,
name: "FF",
},
{
id: 1007,
parentId: 1002,
name: "GG",
},
{
id: 1008,
parentId: 1004,
name: "HH",
},
{
id: 1009,
parentId: 1005,
name: "II",
},
];
暴力解法
暴力一点,直接双层遍历找到父结点并且把自己塞进去
js
function listToSimpleTree(data){
const res = []
data.forEach(item=>{
const parent = data.find(node=>item.parentId === node.id )
if(parent){
parent.children = parent.children || []
parent.children.push(item)
}else{
res.push(item)
}
})
return res
}
空间换时间
暴力解法的时间复杂度为O(n^2),可以通过空间换时间的方式来优化一下...
js
function listToTree(data){
const obj = {}
data.forEach(item=>{
obj[item.id] = item
})
const res = []
data.forEach(item=>{
const parent = obj[item.parentId]
if(parent){
parent.children = parent.children || []
parent.children.push(item)
}else{
res.push(item)
}
})
return res
}
先把每个item以键值对的方式存入obj中,那么就不用再遍历寻找父节点了...
递归
还可以使用递归实现
js
function recursiveToTree(data){
function loop(key){
const arr = []
data.forEach(item => {
if(item.parentId === key){
item.children = loop(item.id)
arr.push(item)
}
})
return arr
}
return loop(0)
}
- 定义一个loop函数,接收一个key值
- 在loop函数中遍历data,找一下parentId为key的结点存入arr
- 在找到结点以后,再递归找到本结点的子结点,直到查找完全return arr
- 一级结点的父结点为0,所以直接返回loop(0)就可以
红绿灯
手写一个红绿灯,红绿黄三个灯依次亮起
js
function red(){
console.log('红');
}
function yellow(){
console.log('黄');
}
function green(){
console.log('绿');
}
function light(cb,wait){
return new Promise((resolve)=>{
setTimeout(()=>{
cb();
resolve();
},wait)
})
}
function lightStep(){
Promise.resolve().then(()=>{
return light(red,3000);
}).then(()=>{
return light(yellow,2000);
})
.then(()=>{
return light(green,1000);
}).finally(()=>{
return lightStep()
})
}
lightStep()
思路非常简单,主要就是通过finally()一直重复调用...
结尾
掘友们还遇见过哪些送分题,来评论区说说...