【近日力扣】 二叉树的前/中/后序遍历+N 叉树的前序/后序遍历+二叉树/N 叉树的层序遍历+二叉树/N 叉树的最大深度

二叉树专题(一)。通用的两种方法——递归和迭代,迭代一定得搞懂,有的题递归搞不定或者很麻烦

二叉树的前/中/后序遍历(简单)

  • 思路:递归。
const postorderTraversal = (root) => {
    if (!root) return []
    let arr = []
    let ergodic = (root) => {
        if (root ===null) return
        // 改变该语句位置即可
        arr.push(root.val) // 前序遍历
        ergodic(root.left)
        // arr.push(root.val),中序遍历
        ergodic(root.right)
        // arr.push(root.val),后序遍历
        return arr
    }
    return ergodic(root)
}
  • 思路:迭代,以后序遍历为例。该方法理解起来就复杂多了——递归其实是自己维护了一个栈,那么迭代的话就是手动构建一个这样的栈,去模拟递归的过程,具体解释请看下列代码的注释
const postorderTraversal = (root) => {
    let res = []
    let stack = [] // 栈
    let pre = null   // 记录刚遍历的节点指针
    while (root|| stack.length) {
        // 入栈,并对左子节点执行相同的操作直到为空
        while(root) {
            stack.push(root)
            root = root.left
        }
        // 取出最后一个压入的节点
        let node = stack.pop()
        // 该节点没有右子节点,或者,这个节点的右子节点,已遍历过
        if (!node.right || node.right === pre) {
            res.push(node.val)
            // 标记刚遍历的节点
            pre = node
            // 根节点指针指向空,下一次循环时,无需压栈操作,直接弹出
            root = null 
        } else {
            // 该节点有右子节点,将节点压入栈
            stack.push(node)
            // 根节点指针指向右子节点
            root = node.right
        }
    }
    return res
}

N 叉树的前序/后序遍历(简单)

  • 思路:递归。和二叉树同理,只不过要处理一下多个子节点的情况,for 循环一遍即可
var preorder = function(root) {
    if (!root) return []
    let arr = []
    let traversal = (root) => {
        if (!root) return
        let len = root.children.length
        arr.push(root.val) // 前序遍历
        for (let i = 0; i < len; i++) {
            traversal(root.children[i])
        }
        // arr.push(root.val),后序遍历
        return arr
    }
    return traversal(root)
};
  • 思路:迭代(以后序遍历为例)。维护一个栈,先压入根节点,然后 while 循环,每次取出栈顶元素,将该值 push 进一个数组保存,再用 for 循环将子节点从左至右的顺序压入栈,如此反复直到栈为空
var preorder = function(root) {
    if (!root) return []
    let arr = []
    let stack = []
    stack.push(root)
    while (stack.length) {
        let node = stack.pop(root)
        arr.push(node.val)
        let len = node.children.length
        for (let i = len - 1; i >= 0; i--) {
            stack.push(node.children[i])
        }
    }
    return arr
};

二叉树的层序遍历(中等)

  • 思路:广度优先搜索(BFS),特点是用了队列数据结构。大致思路为,搜索所有节点,每搜索出一层节点,就存入一个数组,并用 Map 对象的键值对保存,表明该数组是第几层,如此反复,最后遍历 Map 对象将多层数组存入一个数组中即可
var levelOrder = function(root) {
    if (!root) return []
    let res = [], i = 0 // i是表示第i层
    let map = new Map()
    let queue = [] // 维护一个队列
    queue.push(root)
    while (queue.length) {
        let tier = [], len = queue.length
        for (let i = 0; i < len; i++) {
            let node = queue.shift()
            tier.push(node.val)
            if (node.left) queue.push(node.left)
            if (node.right) queue.push(node.right)
        }
        // 保存对应关系,同时i加一
        map.set(i, tier)
        i++
    }
    map.forEach(val => res.push(val))
    return res
};

N 叉树的层序遍历(中等)

  • 思路:广度优先搜索,思路同上,但第二次写我做了些优化——由于子节点不只两个,一开始将子节点存入队列时想的是循环遍历,后来意识到可以用扩展运算符,避免了三层循环嵌套,减少时间复杂度;同时也可以不用 Map 对象进行存储子数组,直接将子数组存入目标数组即可,减少空间复杂度
var levelOrder = function(root) {
    if (!root) return []
    let res = []
    let map = new Map()
    let queue = []
    queue.push(root)
    while (queue.length) {
        let tier = []
        let len = queue.length
        for (let i = 0; i < len; i++) {
            let node = queue.shift()
            tier.push(node.val)
            // 扩展运算符
            if (node.children) queue.push(...node.children)
        }
        // tier直接存入res
        res.push(tier)
    }
    return res
};

二叉树的最大深度(简单)

  • 思路:递归。灵活使用Math.max()函数
var maxDepth = function(root) {
    if (!root) return 0
    // 每次递归加一,意味着节点数加一
    return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1
};

N 叉树的最大深度(简单)

  • 思路:递归。同二叉树,得处理多个子节点,可用 for 循环、扩展运算符
var maxDepth = function(root) {
    if (!root) return 0
    // root.children是数组,空也为真,所以得通过长度判断是否有元素
    if (!root.children.length) return 1
    let arr = []
    for (let item of root.children) {
        arr.push(maxDepth(item))
    }
    return Math.max(...arr) + 1
    // 上面几句可以简化为如下一句
    // return Math.max(...root.children.map(i => maxDepth(i))) + 1
};

如果觉得对你有帮助的话,点个赞呗~

反正发文又不赚钱,交个朋友呗~

如需转载,请注明出处foolBirdd

你可能感兴趣的:(力扣算法题,数据结构,算法,c语言,树结构)