深信服二面

朋友今天面试深信服,需要手写这个题。面完之后把题目分享了一下,下面是我的代码。

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
    }

**当前解决问题对于一些特定类型的数据不能处理,可以参考本人在文章<树与数组的转换>的方法。**如果你能确保你的数据结构可以使用当前的方法,效率会更快一点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值