前端算法面试必刷题系列[43]

257 阅读4分钟

这个系列没啥花头,就是纯 leetcode 题目拆解分析,不求用骚气的一行或者小众取巧解法,而是用清晰的代码和足够简单的思路帮你理清题意。让你在面试中再也不怕算法笔试。

78. 二叉树的层序遍历 (binary-tree-level-order-traversal)

标签

  • 二叉树的层序遍历
  • 中等

题目

leetcode 传送门

这里不贴题了,leetcode打开就行,题目大意:

给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。

示例: 二叉树:[3,9,20,null,null,15,7],

   3
   / \
  9  20
    /  \
   15   7

返回其层序遍历结果:

[
  [3],
  [9,20],
  [15,7]
]

基本思路

这篇思路非常清晰,我不赘述了,看完给他点赞哈! 二叉树的层序遍历

BFS 是按层层推进的方式,遍历每一层的节点。题目要求的是返回每一层的节点值,所以这题用 BFS 来做非常合适。

关于 DFS / BFS 的相关内容 移步这篇哈 DFS + BFS

基本步骤

BFS 需要用队列作为辅助结构,下面是简单说明步骤

  • 我们先将根节点放到队列中,第一层有一个节点,队列长度为 1 ,这个长度也就表示该层有几个节点
  • 取出队列头部node 第一次就是根 值放进该层list 并把它左右子树入队列,(其实就是记录这层有多少岔道)
  • 把该层list 放进结果数组就行了,一层的遍历就完成了,下面第二层同样的操作就行了,继续重复

实现上来说2层循环,外层循环一次代表一层,得到一个列表,放进结果数组,内部循环循环该层队列中的每个节点,并把这层节点的左右子树推到下一层队列中。(因为循环次数为当前层节点个数,所以后面推进去的是下一层循环才会用到)

写法实现

const levelOrderBFS = function(root) {
  let resList = []
  let queue = []

  if (root !== null) {
    queue.push(root)
  }
  
  while(queue.length > 0) {
    let curLevelList = []
    let levelSize = queue.length

    while(levelSize > 0) {
      // 队列先进先出,用shift从队列头取出node并访问
      let node = queue.shift()
      // 把node推进每层的list
      curLevelList.push(node.val)
      // 当前层list长度 - 1
      levelSize--
      // 这个node的左右子树就是下一层的node节点
      // 所以分别把当前取出的node的左右子树推进一个临时列表,作为下层循环的队列
      // 层次遍历从左到右,先进左子树后进右子树
      if(node.left !== null) {
        queue.push(node.left)
      }
      if(node.right !== null) {
        queue.push(node.right)
      }

    }
    // 把当前层list推到结果列表
    resList.push(curLevelList)
  }
  return resList
};

79. 二叉树的锯齿形层序遍历 (binary-tree-zigzag-level-order-traversal)

标签

  • 二叉树的层序遍历
  • 中等

题目

leetcode 传送门

这里不贴题了,leetcode打开就行,题目大意:

给定一个二叉树,返回其节点值的锯齿形层序遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

示例: 给定二叉树 [3,9,20,null,null,15,7],

   3
   / \
  9  20
    /  \
   15   7

返回其层序遍历结果:

[
  [3],
  [20,9],
  [15,7]
]

基本思路

上面一题的变种,思想几乎一模一样,只不过给加个状态位,平时工作中类似打个补丁。直接看代码。

写法实现

const levelOrderBFS = function(root) {
  let resList = []
  let queue = []
  // 添加的就是这个状态位 是否从左边开始
  let isLeftStart = true

  if (root !== null) {
    queue.push(root)
  }
  
  while(queue.length > 0) {
    let curLevelList = []
    let levelSize = queue.length

    while(levelSize > 0) {
      let node = queue.shift()
      // 其实就是这,原来都是 push,现在需要加上进列表方向
      if (isLeftStart) {
        curLevelList.push(node.val);
      } else {
        curLevelList.unshift(node.val);
      }
      levelSize--
      
      if(node.left !== null) {
        queue.push(node.left)
      }
      if(node.right !== null) {
        queue.push(node.right)
      }
    }
    // 下一层反向
    isLeftStart = !isLeftStart
    resList.push(curLevelList)
  }
  return resList
};

另外向大家着重推荐下这位大哥的文章,非常深入浅出,对前端进阶的同学非常有作用,墙裂推荐!!!核心概念和算法拆解系列

今天就到这儿,想跟我一起刷题的小伙伴可以加我微信哦 搜索我的微信号infinity_9368,可以聊天说地 加我暗号 "天王盖地虎" 下一句的英文,验证消息请发给我 presious tower shock the rever monster,我看到就通过,暗号对不上不加哈,加了之后我会尽我所能帮你,但是注意提问方式,建议先看这篇文章:提问的智慧

参考