Letcode 102: 按层遍历二叉树, 112 路径总和问题
Posted Dream_it_possible!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Letcode 102: 按层遍历二叉树, 112 路径总和问题相关的知识,希望对你有一定的参考价值。
目录
一、逐层遍历二叉树(中等)
题目
给你二叉树的根节点
root
,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]
示例 2:输入:root = [1]
输出:[[1]]
示例 3:输入:root = []
输出:[]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
我的解题思路
根据题意,我们需要二叉树的每层遍历结果, 首先我想到的就是广度优先遍历算法,广度优先遍历的结果就是从root到下一层的左子树到右子树,遍历的完后进入到下一层遍历,直到遍历完所有的叶子节点, 叶子节点表示没有子节点的节点。
广度优先遍历:
private static List<Integer> BreadthTraverse(TreeNode<Integer> head)
List<Integer> results = new ArrayList<>();
Queue<TreeNode> queue = new LinkedBlockingQueue<>();
queue.add(head);
while (!queue.isEmpty())
TreeNode<Integer> node = queue.poll();
results.add(node.getVal());
if (node.left != null)
queue.add(node.left);
if (node.right != null)
queue.add(node.right);
return results;
打印的结果是一个列表, 与题意有一点差距,我们需要将一个列表输出按层输出成多个列表,也就是需要在while循环里按层分割列表。
实现思路: 我们可以基于广度优先遍历算法,通过queue的size按层分割,然后按层级弹出所有元素形成一个列表, 同时将该层级的所有左孩子和右孩子压入到队列里为下一层遍历做准备。
public List<List<Integer>> levelOrder(TreeNode root)
if (root == null)
return new LinkedList<>();
List<List<Integer>> results = new LinkedList<>();
Queue<TreeNode> queue = new LinkedBlockingQueue<>();
queue.add(root);
while (!queue.isEmpty())
int queueSize = queue.size();
List<Integer> levelList = new LinkedList<>();
// 按层级弹出所有元素, 同时将该层级的所有左孩子和右孩子压入到队列里为下一层遍历做准备。
for (int i = 0; i < queueSize; i++)
TreeNode node = queue.poll();
levelList.add(node.val);
if (node.left != null)
queue.offer(node.left);
if (node.right != null)
queue.offer(node.right);
results.add(levelList);
return results;
算法的时间复杂度为O(N), 因为只用到了一个队列存放节点元素,空间复杂度为:O(N)。
二、路径总和问题(简单)
题目
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。
叶子节点 是指没有子节点的节点。
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/path-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
我的解题思路
根据题意,我们要求的每个叶子节点到根节点的总路径,因此我们可以在遍历每个节点时想办法记录下每个节点到根节点的距离,如果遍历到叶子节点,那么就比较当前节点到根节点的距离和是否等于target,如果等于那么返回true,如果遍历完了整个树叶没有返回true,那么表示没有找到一条叶子节点到根节点的路径和为target。
例如下面的一棵二叉树,3,5,6 分别为叶子节点,一共包含了3条到根节点的路径,计算总和有没有等于8的路径。
采用深度优先遍历算法,在遍历的时候同时用另外一个栈去保存节点到根节点的距离总和,因为遍历节点时采用的是栈,因此计算总和时也要保持使用栈,与遍历的顺序保持一致,在遍历到每个node的左子树和右子树的时候,将不为空的孩子node加入到栈里,同时将距离总和+孩子node值添加距离总和栈里。
public boolean hasPathSum(TreeNode node, int targetSum)
if (node == null)
return false;
Deque<TreeNode> stack = new LinkedBlockingDeque<>();
// 存放当前节点到根节点的距离和
Deque<Integer> totalValStack = new LinkedBlockingDeque<>();
stack.add(node);
totalValStack.add(node.val);
while (!stack.isEmpty())
TreeNode topNode = stack.pop();
Integer totalVal = totalValStack.pop();
// 如果当前节点为叶子节点,那么就比较targetSum是否与距离总和相等
if (topNode.left == null && topNode.right == null && targetSum == totalVal)
return true;
// 深度优先,先入右子树
if (topNode.right != null)
stack.push(topNode.right);
totalValStack.push(totalVal + topNode.right.val);
if (topNode.left != null)
stack.push(topNode.left);
totalValStack.push(totalVal + topNode.left.val);
return false;
执行结果:
复杂度分析
时间复杂度:O(N),其中 N 是树的节点数, 对每个节点访问一次。
空间复杂度:O(N),其中N 是树的节点数。空间复杂度主要取决于队列的开销,队列中的元素个数不会超过树的节点数。
官方方案
官方推荐方案之一采用的是广度优先遍历算法,使用了2个队列,思想和深度优先遍历算法一样,时间和空间复杂度也是O(N)。
以上是关于Letcode 102: 按层遍历二叉树, 112 路径总和问题的主要内容,如果未能解决你的问题,请参考以下文章