前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >树+8道前端算法面试高频题解

树+8道前端算法面试高频题解

作者头像
童欧巴
发布2021-04-09 16:03:17
4200
发布2021-04-09 16:03:17
举报
文章被收录于专栏:前端食堂前端食堂

读完需要9分钟,速读仅需3分钟

这是前端食堂的第 64 篇原创

美味值:?????

口味:酸菜汆白肉

树的相关名词科普

  • 根节点
  • 叶子节点
  • 父节点
  • 子节点
  • 兄弟节点
  • 高度
  • 深度

A 是 根节点。C、D、F、G 是 叶子节点。A 是 B 和 E 的 父节点。B 和 E 是 A 的 子节点。B、E 之间是 兄弟节点

高度、深度、层 如上图所示。

为了方便理解记忆,高度就是抬头看,深度就是低头看。

高度、深度 不同, 类比盗梦空间里的楼,楼都是从 1 层开始计算,盗梦空间中的楼颠倒过来,从上往下。

开启刷题

  • 前端食堂的 LeetCode 题解仓库[1]

年初立了一个 flag,上面这个仓库在 2021 年写满 100 道前端面试高频题解,目前进度已经完成了 50%。

如果你也准备刷或者正在刷 LeetCode,不妨加入前端食堂,一起并肩作战,刷个痛快。

了解了树的基础知识后,马上开启我们愉快的刷题之旅,我整理了 8 道高频的 LeetCode 链表题及题解如下。

01 二叉树的中序遍历

原题链接[2]

中序遍历:先打印当前节点的左子树,再打印当前节点,最后打印当前节点的右子树 (CBDAFEG),如上图。

代码语言:javascript
复制
const inorderTraversal = function(root) {
    const result = [];
    function pushRoot(root) {
        if (root !== null) {
            if (root.left !== null) {
                pushRoot(root.left);
            }
            result.push(root.val);
            if (root.right !== null) { 
                pushRoot(root.right);
            }
        }
    }
    pushRoot(root);
    return result;
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

02 二叉树的前序遍历

原题链接[3]

前序遍历:先打印当前节点,再打印当前节点的左子树,最后打印当前节点的右子树 (ABCDEFG),如上图。

代码语言:javascript
复制
const preorderTraversal = function(root) {
    const result = [];
    function pushRoot(node){
        if (node !== null) {
            result.push(node.val);
            if (node.left !== null){ 
                pushRoot(node.left);
            }
            if (node.right !== null) {
                pushRoot(node.right);
            } 
        }
    }
    pushRoot(root);
    return result;
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

03 二叉树的后序遍历

原题链接[4]

后序遍历:先打印当前节点的左子树,再打印当前节点的右子树,最后打印当前节点 (CDBFGEA),如上图。

代码语言:javascript
复制
const postorderTraversal = function(root) {
    const result = [];
    function pushRoot(node) {
        if (node !== null) {
            if (node.left !== null) {
                pushRoot(node.left);
            }
            if (node.right !== null) {
                pushRoot(node.right);
            } 
            result.push(node.val);
        }
    }
    pushRoot(root);
    return result;
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

04 相同的树

原题链接[5]

深度优先搜索 DFS

  1. 如果两个二叉树都为空,则它们相同返回 true。
  2. 如果两个二叉树中有一个为空,则它们不同返回 false。
  3. 如果两个二叉树都不为空,首先判断根节点是否相同,不同则返回 false。
  4. 如果两个二叉树的根节点相同,则分别递归判断其左右子树是否相同。
代码语言:javascript
复制
const isSameTree = function(p, q) {
    if (p === null && q === null) return true;
    if (p === null || q === null) return false;
    if (p.val !== q.val) return false;
    return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
};
  • 时间复杂度: O(min(m, n))
  • 空间复杂度: O(min(m, n))

05 对称二叉树

原题链接[6]

递归

先明确,所谓“对称”,也就是两个树的根节点相同

  • 第一个树的左子树与第二个树的右子树镜像对称。
  • 第一个树的右子树与第二个树的左子树镜像对称。
代码语言:javascript
复制
const isSymmetric = function(root) {
    if (root === null) return true
    return isEqual(root.left, root.right) // 比较左右子树是否对称
};

const isEqual = function(left, right) {
    // 递归终止条件
    if (left === null && right === null) return true // 对称
    if (left === null || right === null) return false // 不对称
    // 比较左右子树的 root 值以及左右子树是否对称
    return left.val === right.val
        && isEqual(left.left, right.right)
        && isEqual(left.right, right.left)
}
  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

06 二叉树的层序遍历

原题链接[7]

DFS 深度优先遍历

按照树的深度将每层对应的节点添加到对应层的数组中即可。

代码语言:javascript
复制
const levelOrder = function(root) {
    if (!root) return []
    const res = []
    dfs(root, 0, res)
    return res
};

const dfs = function(root, depth, res) {
    if (!root) return // 递归终止条件
    if (!res[depth]) res[depth] = []
    res[depth].push(root.val) // 存入每层的节点值
    dfs(root.left, depth + 1, res) // drill down
    dfs(root.right, depth + 1, res)
}

BFS 广度优先遍历

根据层次返回其对应的结果集合。

  1. 边界处理,初始化队列 queue 和存放结果的数组 res。
  2. 外层循环遍历层级结构,内层循环遍历每一层的子节点。
  3. 遍历时需要记录当前层的遍历次数 len 以及当前层的节点数组 arr。
  4. 取得 node 依次出队,并依次存入当前层的节点数组中。
  5. 若存在左右子节点,则依次入队,并更新 len。
  6. 遍历完后返回结果 res。
代码语言:javascript
复制
const levelOrder = function(root) {
    if (!root) return []
    const queue = [root]
    const res = []
    while (queue.length > 0) {
      const arr = []
      let len = queue.length
      while (len) {
        let node = queue.shift()
        arr.push(node.val)
        if (node.left) queue.push(node.left)
        if (node.right) queue.push(node.right)
        len--
      }
      res.push(arr)
    }
    return res
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

07 二叉树的最大深度

原题链接[8]

DFS 深度优先搜索

树的深度 = 左右子树的最大深度 + 1

代码语言:javascript
复制
const maxDepth = function(root) {
    if (!root) { // 递归终止条件
        return 0
    } else {
        const left = maxDepth(root.left)
        const right = maxDepth(root.right)
        return Math.max(left, right) + 1
    }
};
  • 时间复杂度: O(n)
  • 最坏空间复杂度: O(height), height 表示二叉树的高度

BFS 广度优先搜索

层序遍历时记录树的深度。

二叉树的层序遍历可参考轻松拿下二叉树的层序遍历[9]

代码语言:javascript
复制
const maxDepth = function(root) {
    let depth = 0
    if (root === null) {
        return depth
    }
    const queue = [root]
    while (queue.length) {
        let len = queue.length
        while (len--) {
            const cur = queue.shift()
            cur.left && queue.push(cur.left)
            cur.right && queue.push(cur.right)
        }
        depth++
    }
    return depth
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

08 翻转二叉树

原题链接[10]

Google:我们 90% 的工程师都用你写的软件(Homebrew),但你没法在白板上翻转二叉树,所以翻滚吧,蛋炒饭。

原推截图,至今仍在。Max Howell 当年吐槽之后 LeetCode 马上加入了这道题。

会了这道题,是不是我们也可以超越世界级大牛了?(狗头保命)

首先明确,所谓二叉树的翻转需要满足以下两点:

  1. 它的左右子树要交换位置。
  2. 并且左右子树内部的所有子树或是结点都要进行交换位置。

递归

  1. 从根节点开始,递归的对树进行遍历。
  2. 从叶子结点开始进行翻转。
  3. 左右子树都已经翻转后,交换两棵子树的位置即可完成全部的翻转。
代码语言:javascript
复制
const invertTree = function(root) {
    if (root === null) return null // 递归终止条件
    invertTree(root.left)
    invertTree(root.right)
    const temp = root.left
    root.left = root.right
    root.right = temp
    return root
}
  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

当然你也可以将上面的 2,3 两个步骤颠倒执行,也就是先交换两棵子树的位置,再对其内部进行翻转。

代码语言:javascript
复制
const invertTree = function(root) {
    if (root === null) return null // 递归终止条件
    const temp = root.left
    root.left = root.right
    root.right = temp
    invertTree(root.left)
    invertTree(root.right)
    return root
}

BFS

层序遍历遍历二叉树,当根结点出列时,翻转它的左右子树。然后将其左右子节点入列,以便下一层时翻转。

二叉树的层序遍历可参考轻松拿下二叉树的层序遍历[11]

代码语言:javascript
复制
const invertTree = (root) => {
  if (root == null) return null;
  const queue = [root];
  while (queue.length) {
    const cur = queue.shift();
    [cur.left, cur.right] = [cur.right, cur.left];
    if (cur.left) queue.push(cur.left);
    if (cur.right) queue.push(cur.right);
  }
  return root;
}

参考资料

[1]

前端食堂的 LeetCode 题解仓库: https://github.com/Geekhyt/javascript-leetcode

[2]

原题链接: https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/qian-duan-shi-tang-ti-jie-chao-hao-li-ji-c254/

[3]

原题链接: https://leetcode-cn.com/problems/binary-tree-preorder-traversal/solution/qian-duan-shi-tang-ti-jie-chao-hao-li-ji-pgjc/

[4]

原题链接: https://leetcode-cn.com/problems/binary-tree-postorder-traversal/solution/qian-duan-shi-tang-ti-jie-chao-hao-li-ji-2k93/

[5]

原题链接: https://leetcode-cn.com/problems/same-tree/solution/qian-duan-shi-tang-ti-jie-chao-hao-li-ji-etrd/

[6]

原题链接: https://leetcode-cn.com/problems/symmetric-tree/solution/qian-duan-shi-tang-ti-jie-chao-hao-li-ji-66dv/

[7]

原题链接: https://leetcode-cn.com/problems/binary-tree-level-order-traversal/solution/qian-duan-shi-tang-ti-jie-chao-hao-li-ji-jj2g/

[8]

原题链接: https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/solution/qian-duan-shi-tang-ti-jie-chao-hao-li-ji-im8f/

[9]

轻松拿下二叉树的层序遍历: https://leetcode-cn.com/problems/binary-tree-level-order-traversal/solution/qian-duan-shi-tang-ti-jie-chao-hao-li-ji-jj2g/

[10]

原题链接: https://leetcode-cn.com/problems/invert-binary-tree/solution/qian-duan-shi-tang-ti-jie-chao-hao-li-ji-j4jr/

[11]

轻松拿下二叉树的层序遍历: https://leetcode-cn.com/problems/binary-tree-level-order-traversal/solution/qian-duan-shi-tang-ti-jie-chao-hao-li-ji-jj2g/

公众号:前端食堂

知乎:童欧巴

掘金:童欧巴

这是一个终身学习的男人,他在坚持自己热爱的事情,欢迎你加入前端食堂,和这个男人一起开心的变胖~

“如果你觉得读了本文有收获的话可以点个在看让我看到。阅读过程中有任何问题、想法或者感触也欢迎你在下方留言,也可以在后台回复加群进入食堂的交流群。 沟通创造价值,分享带来快乐。也欢迎你分享给身边有需要的同学,利他就是最好的利己。 ”

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-03-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端食堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 树的相关名词科普
  • 开启刷题
    • 01 二叉树的中序遍历
      • 02 二叉树的前序遍历
        • 03 二叉树的后序遍历
          • 04 相同的树
            • 深度优先搜索 DFS
          • 05 对称二叉树
            • 递归
          • 06 二叉树的层序遍历
            • DFS 深度优先遍历
            • BFS 广度优先遍历
          • 07 二叉树的最大深度
            • DFS 深度优先搜索
            • BFS 广度优先搜索
          • 08 翻转二叉树
            • 递归
            • BFS
            • 参考资料
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档