leetcode算法专题-树

64 阅读3分钟

🌲 树的专题集合

  • 二叉树的中序遍历
  • 二叉树的前序遍历
  • 二叉树的后序遍历
  • 二叉树的层序遍历

94. 二叉树的中序遍历

给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。

image.png

定义:按照访问左子树——根节点——右子树的方式遍历这棵树,而在访问左子树或者右子树的时候我们按照同样的方式遍历,直到遍历完整棵树。

递归算法

我个人觉得想明白递归的一个关键就是放心地把下一步交给下一次的调用,不要在脑子里往深了想。

遵循左中右的调用顺序,直到结点为空时,终止递归

var inorderTraversal = function(root) {
    let res=[]
    const func=(root)=>{
        if(!root) return
        func(root.left)
        res.push(root.val)
        func(root.right)
    }
    func(root)
    return res
};

迭代算法

迭代算法就是将递归中隐式的调用栈,显式的自己实现一遍

var inorderTraversal = function(root) {
    let res=[]
    let stack=[]
    while(root || stack.length) {
        // 将左子树全部依次从上到下压入栈中
        while(root) {
        stack.push(root)
        root=root.left
        }
        root=stack.pop()
        res.push(root.val)
        root=root.right
    }
    return res
};

144. 二叉树的前序遍历 给你二叉树的根节点 root ,返回它节点值的 前序 **遍历。

image.png

定义:按照访问根节点——左子树——右子树的方式遍历这棵树,而在访问左子树或者右子树的时候,我们按照同样的方式遍历,直到遍历完整棵树。

递归算法

var preorderTraversal = function(root) {
    let res=[]
    const func=(root)=>{
        if(!root) return
        res.push(root.val)
        func(root.left)
        func(root.right)
    }
    func(root)
    return res
};

迭代算法

var preorderTraversal = function (root) {
    let res = []
    if (!root) return res
    let stack = []
    stack.push(root)
    while (stack.length) {
        root = stack.pop()
        res.push(root.val)
        if (root.right) stack.push(root.right)
        if (root.left) stack.push(root.left)
        // 此处先右后左的顺序压栈是为了让出栈顺序为左右
    }
    return res
};

145. 二叉树的后序遍历 给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历

image.png

定义:按照访问左子树——右子树——根节点的方式遍历这棵树,而在访问左子树或者右子树的时候,我们按照同样的方式遍历,直到遍历完整棵树。

递归算法

var postorderTraversal = function(root) {
    let res=[]
    const func=(root) => {
        if(!root) return
        func(root.left)
        func(root.right)
        res.push(root.val)
    }
    func(root)
    return res
};

迭代算法

var postorderTraversal = function (root) {
    let res = []
    let stack = []
    while (root || stack.length) {
        res.unshift(root.val)
        if (root.left) stack.push(root.left)
        if (root.right) stack.push(root.right)
        root = stack.pop()
    }
    return res
};

可以看出来,递归的套路都是一样的只不过根据前序、中序、后序遍历的调用顺序不太一样

二叉树的层序遍历

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

image.png

层次遍历通常使用queue队列这种结构来实现,根据先进先出的原则,依次将每一层结点的左右子树放入队列中再到下一层依次从头取出,遍历并循环进行将左右子树放入队列中。 javascript中没有队列这种结构,所以用到的只是这个先进先出的思想,由数组的shift()方式实现

var levelOrder = function (root) {
    let res = []
    if (!root) return res
    let level = 1
    let queue = []
    queue.push(root)
    while (queue.length) {
        let size = queue.length
        let arr=[]
        for (let i = 0; i < size; i++) {
            let root = queue.shift()
            arr.push(root.val)
            if (root.left || root.right) {
                if (root.left) queue.push(root.left)
                if (root.right) queue.push(root.right)
            }
        }
        res.push(arr)
    }
    return res
};