持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情
LeetCode 75 —— 102. 二叉树的层序遍历
一、题目描述:
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
示例 1:
输入: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… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、思路分析:
-
这道题考察了什么思想?你的思路是什么?
看到这道题目,在我脑子里蹦出来的就是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对应深度的位置。
-
做题的时候是不是一次通过的,遇到了什么问题,需要注意什么细节?
不是的,刚开始没什么思路,不知道dfs时还需要传递深度,还需要多做几遍复习巩固。
-
有几种解法,哪种解法时间复杂度最低,哪种解法空间复杂度最低,最优解法是什么?其他人的题解是什么,谁的效率更好一些?用不同语言实现的话,哪个语言速度最快?
下面我们来看大佬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 }
四、总结:
深度优先遍历、广度优先遍历都是我们应该掌握的技能,这道题目DFS、BFS解法都应该掌握。如果我们使用 DFS/BFS 只是为了遍历一棵树、一张图上的所有结点的话,那么 DFS 和 BFS 的能力没什么差别,我们当然更倾向于更方便写、空间复杂度更低的 DFS 遍历。不过,某些使用场景是 DFS 做不到的,只能使用 BFS 遍历。
写作模板:
作者:掘金酱
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。