110.平衡二叉树 (优先掌握递归)
平衡二叉树: 是指该树所有节点的左右子树的深度相差不超过 1。
这道题我一开始没有想到所有节点这个重点。于是产生了错误的代码:
错误代码记录:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//尝试使用递归
//然后想法是将一棵树分为两棵树。 然后分别计算左子树和右子树的最大深度
// int leftMaxDepth=0;
// int rightMaxDepth=0;
public boolean isBalanced(TreeNode root) {
if(root==null)
return true;
//如果左右子树的深度超过1,返回false 否则返回true;
if(Math.abs(calcMaxDepth(root.left,0)-calcMaxDepth(root.right,0))>1)
return false;
return true;
}
//考虑使用递归方法——后序遍历,通过计算高度来得到深度
//后序遍历————左右中
public int calcMaxDepth(TreeNode node,int depth){
if(node==null)
return 0;
//通过递归计算左子树的最大深度
int depth1=calcMaxDepth(node.left,depth);
//通过递归计算右子树的最大深度
int depth2=calcMaxDepth(node.right,depth);
//计算本节点的最大深度
return Math.max(depth1,depth2)+1;
}
}
上面代码忽略掉的情况如下图所示:比如左子树中的2,它的左子树深度是2,右子树深度是0,所以它并不满足平衡二叉树的定义——所有节点左右子树深度不超过1。
正确的代码如下:(个人的)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//尝试使用递归
//然后想法是将一棵树分为两棵树。 然后分别计算左子树和右子树的最大深度
//加入一个关键的全局标志性变量。用于记录这棵树是不是平衡二叉树
int flag=0;
public boolean isBalanced(TreeNode root) {
if(root==null)
return true;
calcMaxDepth(root,0);
if(flag==-1)
return false;
return true;
}
//考虑使用递归方法——后序遍历,通过计算高度来得到深度
//后序遍历————左右中
public int calcMaxDepth(TreeNode node,int depth){
if(node==null)
return 0;
//通过递归计算左子树的最大深度
int depth1=calcMaxDepth(node.left,depth);
//通过递归计算右子树的最大深度
int depth2=calcMaxDepth(node.right,depth);
//如果左右子树的最大深度之差大于1 那么全局的标志性变量flag变为-1
if(Math.abs(depth1-depth2)>1){
flag=-1;
}
//计算本节点的最大深度
return Math.max(depth1,depth2)+1;
}
}
上面的代码:一开始我想直接在递归函数中判断,一旦左右子树的最大深度之差大于1,直接跳出整个递归函数(因为此时这棵树一定已经不是平衡二叉树了)。但是递归的特性导致无法直接跳出整个递归函数(除非选择抛出异常,并在调用递归函数的地方捕获这个异常;但这显然不是一个好的方法) 所以选择创建一个“全局变量”用来记录。
257. 二叉树的所有路径 (优先掌握递归)
这是大家第一次接触到回溯的过程, 我在视频里重点讲解了 本题为什么要有回溯,已经回溯的过程。
如果对回溯 似懂非懂,没关系, 可以先有个印象。
题目链接/文章讲解/视频讲解:代码随想录
404.左叶子之和 (优先掌握递归)
所谓左叶子的概念:首先它要是个叶子节点,其次它是它父节点的左节点。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//考虑使用层序遍历来完成
public int sumOfLeftLeaves(TreeNode root) {
//迭代方法层序遍历 一般都会用到队列
//初始化队列
Queue<TreeNode> queue=new LinkedList<>();
//题目中的提示已经说明了节点数在[1,1000],所以root不可能为空
queue.offer(root);
int sum=0; //用于记录树中的左叶子元素总和
while(!queue.isEmpty()){
//获取当前层的节点个数
int len=queue.size();
while(len>0){
TreeNode curNode=queue.poll();
len--;
//先把下一层的节点入队
//左节点入队
if(curNode.left!=null)
queue.offer(curNode.left);
//右节点入队
if(curNode.right!=null)
queue.offer(curNode.right);
if(curNode.left!=null && curNode.left.left==null && curNode.left.right==null){
sum+=curNode.left.val;
}
}
}
return sum;
}
}