代码随想录算法训练营第17天|110.平衡二叉树、257.二叉树的所有路径、404.左叶子之和
一. 二叉树相关算法题
110.平衡二叉树
递归
思路
- 深度: 根节点到当前节点的长度, 深度是从上到下查所以是前序遍历(中左右)
- 高度: 当前节点到最后一个叶子节点的长度,高度是从下往上所以使用后序遍历(左右中)
- 本题是比较左右高度那么适用后序递归遍历
- 递归入参出参: int getHeight(TreeNode node);
- 递归终止条件: 如果节点为空返回0
- 单层递归逻辑:计算左右子树高度,左右高度差绝对值大于1就不是平衡二叉树 如果小于等于1 返回当前节点的高度1+max(子树高度)
具体代码如下:
class Solution {
public boolean isBalanced(TreeNode root) {
if (getHeight(root)==-1){
return false;
}
return true;
}
public int getHeight(TreeNode cur){
// 如果当前节点为空直接返回高度为0
if (cur == null) return 0;
// 如果左子树不是完全二叉树直接返回-1
int leftHeight = getHeight(cur.left);
if (leftHeight == -1) return -1;
// 如果当前节点的左子树不是完全二叉树直接返回-1
int rightHeight = getHeight(cur.right);
if (rightHeight == -1) return -1;
// 判断当前节点是否完全二叉树
if (Math.abs(leftHeight-rightHeight)>1){
return -1;
} else {
// 如果是完全二叉树返回当前节点的高度
return 1+Math.max(leftHeight,rightHeight);
}
}
}
257.二叉树的所有路径
递归
思路
- 本题需要递归与回溯相结合
- 回溯: 遍历完每个人末端左分支后就要回溯到上一节点遍历末端右分支组成新序列
- 递归终止条件为当前节点的左右节点都为空,此时需要序列化路径为字符串保存然后回溯
class Solution {
public List<String> binaryTreePaths(TreeNode root) {
List<String> result= new ArrayList<>();
List<Integer> path = new ArrayList<>();
// @1
if (root == null) return result;
getPaths(root,path,result);
return result;
}
public void getPaths(TreeNode cur, List<Integer> path, List<String> result) {
//中 在@1,2,3 处判断了当前节点不能为空所以末端空节点不会进入递归
path.add(cur.val);//因为下面递归终止条件 没有判断当前节点是否为空所以把当前节点加入逻辑提前
// 递归终止条件:当前节点的左右节点为空,将路径转为字符串记录下来
if (cur.left == null && cur.right == null){
StringBuilder sPath = new StringBuilder();
for (int i = 0; i < path.size()-1; i++) {
sPath.append(path.get(i)).append("->");
}
sPath.append(path.get(path.size()-1));
result.add(sPath.toString());
}
//每层递归逻辑
//前序遍历
//左 @2
if (cur.left != null) {
getPaths(cur.left,path,result);
//左子树递归完回溯剔除最后一个节点
path.remove(path.size()-1);
}
//右 @3
if (cur.right != null) {
getPaths(cur.right,path,result);
//右子树递归完回溯剔除最后一个节点
path.remove(path.size()-1);
}
}
}
404.左叶子之和
递归
思路
- 首先通过自身节点是不能判断自己是否为左叶子节点的,要通过父节点判断:父节点的左叶子不为空且左叶子的左右叶子都为空就可以判断当前节点为叶子节点
- 另外需要注意右子树也可能存在左叶子节点,需要同步计算
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
// 递归终止条件
if (root == null) return 0;
//因为当前节点的计算放在了父节点所以到达左叶子节点本身不用做操作
if (root.left == null && root.right == null) return 0;
int left = sumOfLeftLeaves(root.left);
//判断叶子节点是否为左节点 如果为左节点上一行的值为0
if (root.left != null && root.left.left == null && root.left.right == null) {
left = root.left.val;
}
// 计算右子树的左叶子节点
int right = sumOfLeftLeaves(root.right);
return left + right;
}
}