【震惊】扁平化转树状结构都用递归么?

151 阅读3分钟

疫情

    由于原因,面试基本都改成了线上,相比线下,线上更能考核手写代码,毕竟大家都经历过先是牛客网的算法题面试,然后是线下一面,线上面试有效的把这两者整合到了一起,也有了更多考验真实处理部分业务场景下遇到问题的代码能力。

问题

    今天偶然看见这个问题,让我想起之前一些面试er的回答,十分有趣。基本上面试十个人十个都是以递归思路解决的,当然大部分是没有解决的(因为写着写着就把自己绕晕了)。
    那么就摒弃代码的实现,专注问题的本质,简单地聊聊思路。如果你想看代码实现,请去baidu搜索即可,一大堆。
   // transfer 
   const a = [
       {name:'1', value:1, id:1, pid:0},
       {name:'2', value:2, id:2, pid:1},
       {name:'3', value:3, id:3, pid:2},
   ]
   // into
   const b = {
       id:1,
       name:'1',
       value:'1',
       children:[
           {
               id:2,
               name:'2',
               value:2,
               children:[
                   {
                       id:3,
                       name:'3',
                       value:3,
                       children:null
                   }
               ]
           }
       ]
   }

思路

    相信大家都遇到过或实际解决过这个问题。很多developer的第一想法就是递归,我也如此 ==> 同样的结构,同样的嵌套,不知道多少层,每层不知道有多少个,肯定是不断的调用同一种实现即递归。
    然后我们就开始以递归为基础实现:
  • 遍历同层
  • 如果没有找到pid相同,就要重新遍历第一层children
  • 把遍历项放入pid相同的target的children字段中
  • 递归以上
    发现好麻烦,并且写了一会就把自己绕进去了,并且以后如果有结构上的扩展,还要在通用的递归逻辑里增添定制化逻辑,那就意味着每一层,每一个都要进行该逻辑的判断组装,那么此刻你还记得你刚才脑子里形成的递归结构么?如果你也十分头疼,那么恭喜你,你已经被递归的黑洞吸了进去。
    且不说递归你到底能不能实现,就算实现了,这个时间复杂度你考虑考虑,深层遍历,同层遍历,如果结构有100层呢?这是我们从心智上无法承受的。那么最大的问题就是循环,如果我们只循环一次呢?把时间控制在O(n),这是不是近乎完美了(因为循环是必须的)。
  • 问题的本质: 构建一个父子关系,能够让我们使用这个满足父子关系的结构,并且子结构可以放在父结构的children字段中。
  • 想要的结果: 我们需要尽量少的遍历,尽量少的递归,构建出来这组关系。
  • 放在children中,children字段是个Array,是个Array...bingo!

谜语:如果我改变,能让你改变,你和我的表象不一,但变化相同。如果你想到了,就成功了。

   const b = [
       {name:'1', value:1, id:1, pid:0, children:[pid=1的item]},
       {name:'2', value:2, id:2, pid:1, children:[pid=2的item]},
       {name:'3', value:3, id:3, pid:2, children:null},
   ]

所以,评论区告诉我,谜底是什么?
解决的思路会随着你们的答案放在评论区。