朋友今天面试深信服,需要手写这个题。面完之后把题目分享了一下,下面是我的代码。
let tree = [
{ name: ‘A’ },
{
name: ‘B’,
children: [
{ name: ‘A’ },
{ name: ‘D’, children: [] }
]
},
{ name: ‘C’ }
]
实现一个函数,加入我输入 A,返回
[
{ name: 'A' },
{
name: 'B',
children: [
{ name: 'A' },
]
}
]
输入B,返回
[
{
name: 'B',
children: [
{ name: 'A' },
{ name: 'D', children: [] }
]
}
]
输入D返回
[
{
name: 'B',
children: [
{ name: 'D', children: [] }
]
}
]
解题思路:
先明白题意,找到name为输入fileName的后代及其祖辈所在树。
此类题,我们一般采用递归,那么递归的领界是什么?注意需要找到name为fileName的,那么我们临界就是刚好找到一个数组中只含有一个元素,并且他的这个元素有一个name属性为fileName。其余情况如果数组有多个元素那么我们需要找每一个元素,在找每个元素的时候我们可以通过JSON.stringify将对象转为json字符串,那么我们可以使用includes方法找,这样可以提高程序的性能,如果该树上存在,那么我们就要判断这个树节点的name是不是我们要找的,如果是我们则需要将其push到我们需要返回的数组中,如果不是则说明在这个树节点的children中,此时我们需要对改树节点的children进行分析,所以此时可以递归调用findFileName函数,并将返回值作为children的属性值,将原来树节点的name依然作为name。然后将这个结果push到我们的数组中。
function findFileName(fileName, treeList) {
if (treeList.length == 1 && treeList[0].name == fileName) {
return treeList
}
let arr = []
treeList.forEach(item => {
if (JSON.stringify(item).includes(`"name":"${fileName}"`)) {
//item => obj
if (item.name == fileName) {
arr.push(item)
} else if (item.children && item.children.length) {
arr.push({
name: item.name,
children: findFileName(fileName, item.children)
})
}
}
})
return arr
}
题目提升,我们输入是一个数组。
function findFileName(fileNameList, treeList) {
if (treeList.length == 1 && fileNameList.includes(treeList[0].name)) {
return treeList
}
// treeList为数组
let arr = []
treeList.forEach(item => {
let treeNodeStr = JSON.stringify(item)
if (fileNameList.find(fileName => treeNodeStr.includes(`"name":"${fileName}"`))) {
//item => obj
if (fileNameList.includes(item.name)) {
arr.push(item)
} else if (item.children && item.children.length) {
arr.push({
name: item.name,
children: findFileName(fileNameList, item.children)
})
}
}
})
return arr
}
升级:如果输入的数组需要按照最小树呢
输入['A','B']输出: [
{ name: 'A' },
{
name: 'B',
children: [
{ name: 'A' },
]
}
]
输入['B'],返回
[
{
name: 'B',
children: [
{ name: 'A' },
{ name: 'D', children: [] }
]
}
]
输入['B','C']输出
[
{
name: 'B',
children: [
{ name: 'A' },
{ name: 'D', children: [] }
]
},
{ name: 'C' }
]
输入['C','D']输出
[
{
name: 'B',
children: [
{ name: 'D', children: [] }
]
},
{ name: 'C' }
]
function findFileName(fileNameList, treeList) {
if (treeList.length == 1 && fileNameList.includes(treeList[0].name)) {
return treeList
}
// treeList为数组
let arr = []
treeList.forEach(item => {
let treeNodeStr = JSON.stringify(item)
if (fileNameList.find(fileName => treeNodeStr.includes(`"name":"${fileName}"`))) {
if (item.children && item.children.length && fileNameList.find(fnc => JSON.stringify(item.children).includes(`"name":"${fnc}"`))) {
arr.push({
name: item.name,
children: findFileName(fileNameList, item.children)
})
} else {
arr.push(item)
}
}
})
return arr
}
**当前解决问题对于一些特定类型的数据不能处理,可以参考本人在文章<树与数组的转换>的方法。**如果你能确保你的数据结构可以使用当前的方法,效率会更快一点。