LeetCode 75 —— 102. 二叉树的层序遍历

64 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情

LeetCode 75 —— 102. 二叉树的层序遍历

一、题目描述:

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

示例 1:

image-20221008111848438

输入:root = [3,9,20,null,null,15,7] 输出:[[3],[9,20],[15,7]] 示例 2:

输入:root = [1] 输出:[[1]] 示例 3:

输入:root = [] 输出:[]

提示:

树中节点数目在范围 [0, 2000] 内 -1000 <= Node.val <= 1000

来源:力扣(LeetCode)

链接:leetcode.cn/problems/bi… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、思路分析:

  1. 这道题考察了什么思想?你的思路是什么?

    看到这道题目,在我脑子里蹦出来的就是DFS,毕竟是遍历二叉树,想到DFS还是很正常吧。我们先设置遍历返回条件——当node等于nil,即某个节点不存在时,就不需要继续往更深的地方前进了。因为返回的是一个二维切片,每层要append的话,需要初始化,因此当result切片的长度小于等于当前深度的时候,我们就初始化一个切片放入result,以便当前深度的节点值能够放入。

    result[depth] = append(result[depth],node.Val)
    dfs(node.Left,depth+1)
    dfs(node.Right,depth+1)
    

    这部分代码是精髓,将节点值放入对应深度的切片,然后往更深处走时会传递深度,以便放入result对应深度的位置。

  2. 做题的时候是不是一次通过的,遇到了什么问题,需要注意什么细节?

    不是的,刚开始没什么思路,不知道dfs时还需要传递深度,还需要多做几遍复习巩固。

  3. 有几种解法,哪种解法时间复杂度最低,哪种解法空间复杂度最低,最优解法是什么?其他人的题解是什么,谁的效率更好一些?用不同语言实现的话,哪个语言速度最快?

    下面我们来看大佬nettee用的BFS方法,使用了队列来完成遍历。确实DFS本质上是使用栈完成遍历,只是不需要我们自己去维护一个栈,我们使用系统的栈即可。

    void bfs(TreeNode root) {
        Queue<TreeNode> queue = new ArrayDeque<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll(); // Java 的 pop 写作 poll()
            if (node.left != null) {
                queue.add(node.left);
            }
            if (node.right != null) {
                queue.add(node.right);
            }
        }
    }
    ​
    作者:nettee
    链接:https://leetcode.cn/problems/binary-tree-level-order-traversal/solution/bfs-de-shi-yong-chang-jing-zong-jie-ceng-xu-bian-l/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    
    /**
     * Definition for a binary tree node.
     * type TreeNode struct {
     *     Val int
     *     Left *TreeNode
     *     Right *TreeNode
     * }
     */
    ​
    func levelOrder(root *TreeNode) [][]int {
        res := [][]int{}
        q := []*TreeNode{}
        if root != nil{
            q = append(q, root)
        }
        
        for i := 0; len(q) > 0; i++ {
            res = append(res, []int{})
            p := []*TreeNode{}
            for j := 0; j < len(q); j++ {
                node := q[j]
                res[i] = append(res[i], node.Val)
                if node.Left != nil{
                    p = append(p, node.Left)
                }
                if node.Right != nil{
                    p = append(p, node.Right)
                }
            }
            q = p
        }
        return res
    }
    ​
    作者:acvv_yaojun
    链接:https://leetcode.cn/problems/binary-tree-level-order-traversal/solution/by-acvv_yaojun-kp6e/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    

三、AC 代码:

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func levelOrder(root *TreeNode) [][]int { 
    var result [][]int
​
    var dfs func(*TreeNode,int)
    dfs = func(node *TreeNode, depth int) {
        if node == nil {
            return
        }
        if len(result) <= depth {
            result = append(result, []int{})
        }
        result[depth] = append(result[depth],node.Val)
        dfs(node.Left,depth+1)
        dfs(node.Right,depth+1)
    }
​
    dfs(root,0)
    return result
}
​
​

image-20221008113631330

四、总结:

深度优先遍历、广度优先遍历都是我们应该掌握的技能,这道题目DFS、BFS解法都应该掌握。如果我们使用 DFS/BFS 只是为了遍历一棵树、一张图上的所有结点的话,那么 DFS 和 BFS 的能力没什么差别,我们当然更倾向于更方便写、空间复杂度更低的 DFS 遍历。不过,某些使用场景是 DFS 做不到的,只能使用 BFS 遍历。

写作模板:

作者:掘金酱

链接:juejin.cn/post/706970…

来源:稀土掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。