110.平衡二叉树 257. 二叉树的所有路径 404.左叶子之和
110.平衡二叉树 (优先掌握递归)
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。
示例 1:
给定二叉树 [3,9,20,null,null,15,7]
返回 true 。
示例 2:
给定二叉树 [1,2,2,3,3,null,null,4,4]
返回 false 。
思路
递归法 后序遍历
使用递归方法求出左右子树的深度,并求出左右子树的差,这个流程为后序遍历
题目要求一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。如果超过 1,则该树不是平衡二叉树
所以需要对左右子树的差进行判断,超过一则不符合条件
代码如下
// 时间复杂度o(n)
// 空间复杂度o(n)
public static boolean isBalanced(TreeNode root) {
if (root == null)
return true;
int result = isTree(root);
if(result == -1)
return false;
return true;
}
public static int isTree(TreeNode node) {
if (node == null)
return 0;
int leftDepth = isTree(node.left);
if(leftDepth == -1)
return -1;
int rightDepth = isTree(node.right);
if(rightDepth == -1)
return -1;
int cha = Math.abs(leftDepth - rightDepth);
if (cha > 1) {
return -1;
}
return Math.max(leftDepth, rightDepth) + 1;
}
问题
我开始的写法,想在递归方法中使用boolean isBalance作为判断平衡二叉树的条件
调用递归算法结束后,判断isBalance的值即可。
但是在调试中发现,isBalance的值没有改动过。
错误代码:猜测时布尔类型引用传递的问题
public static boolean isBalanced(TreeNode root) {
if (root == null)
return true;
boolean isBalance = true;
isTree(root, isBalance);
return isBalance;
}
public static int isTree(TreeNode node, boolean isBalance) {
if (node == null)
return 0;
int leftDepth = isTree(node.left, isBalance);
int rightDepth = isTree(node.right, isBalance);
int cha = Math.abs(leftDepth - rightDepth);
if (cha > 1) {
isBalance = false;
}
return Math.max(leftDepth, rightDepth) + 1;
}
257. 二叉树的所有路径 (优先掌握递归)
给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
思路
递归法 前序遍历
题目要求根节点到所有叶子结点的路径,那么我们需要先访问根节点,然后一层层向下访问直至叶子结点,那么前序遍历符合先访问根节点的条件
这道题目需要用到回溯回退路径,来进入下一个路径,那么在遍历结束后,去除路径的最后一个结点
回溯和递归是息息相关的,有一个递归就要有一个回溯
递归法三要素
方法的入参和返回值 : TreeNode node List String result List String path
方法的中止条件: 到叶子结点中止,记录路径
核心逻辑:前序遍历,有一个递归就要有一个回溯
代码如下
// 时间复杂度o(n)
// 空间复杂度o(n)
public List<String> binaryTreePaths(TreeNode root) {
List<String> result = new ArrayList<>();
List<String> path = new ArrayList<>();
if (root == null)
return result;
preOrder(root, result, path);
return result;
}
public void preOrder(TreeNode node, List<String> result, List<String> path) {
path.add(String.valueOf(node.val));
if (node.left == null && node.right == null) {// 终止条件 找到叶子节点
String str = "";
for (int i = 0; i < path.size(); i++) {
if (i == path.size() - 1) {
str = str + path.get(i);
} else {
str = str + path.get(i) + "->";
}
}
result.add(str);
return;
}
if (node.left != null) {
preOrder(node.left, result, path);
path.remove(path.size() - 1);
}
if (node.right != null) {
preOrder(node.right, result, path);
path.remove(path.size() - 1);
}
}
404.左叶子之和 (优先掌握递归)
计算给定二叉树的所有左叶子之和。
示例:
思路
递归法
后序遍历 计算左右子树中的所有左叶子结点的值,并返回
那么怎么判断当前的叶子结点是左叶子结点呢?
这里定义一个常量sum.
sum = 0表示该节点是由父节点的左结点,sum = 1表示该节点是父结点的右节点
在递归遍历左节点时,将sum = 0作为入参。 遍历右节点,将sum = 1作为入参。用于表示当前结点是左右结点
接下来在中止条件中加以判断,如果sum = 0,当前叶子结点为左节点,返回当前叶子结点的值
否则为当前叶子结点为右节点,返回0
代码如下
// 时间复杂度o(n)
// 空间复杂度o(n)
public int sumOfLeftLeaves(TreeNode root) {
if(root == null)
return 0;
return preOrder(root,0);
}
public int preOrder(TreeNode node, int sum) {
if (node.left == null && node.right == null && sum == 0) {
return node.val;
}
if (node.left == null && node.right == null && sum == 1) {
return 0;
}
int result = 0;
if (node.left != null) {
int leftValue = preOrder(node.left, 0);
result = result + leftValue;
}
if (node.right != null) {
int rightValue = preOrder(node.right, 1);
result = result + rightValue;
}
return result;
}