目录
110.平衡二叉树
平衡二叉树:左右子树的高度差不超过1.
左右子树的高度差不超过1并且也是平衡子树所以构成最后的平衡二叉树
一开始debug没有通过的版本是将高度差不超过1直接return true,然后最后return左右子树是否是平衡子树,这边错误的原因是,如果高度差不超过1走if逻辑的话,可以走最后是否是平衡子树逻辑的就是高度差会超过1的时候。两者之间并非是否则的非此即彼的关系,而是相与。
平衡二叉树:左右子树的高度差不超过1.&&左右子树也是平衡二叉树
自顶向下的递归:height会重复计算(前序遍历),时间复杂度O(n^2)
class Solution {
/**
* 判断是否为平衡二叉树
*
* @param root
* @return
*/
public boolean isBalanced(TreeNode root) {
if (root == null) {
return true;
}
int leftlen = getLength(root.left);
int rightlen = getLength(root.right);
// if (Math.abs(leftlen - rightlen) <= 1) {
// return true;
// }
return Math.abs(leftlen - rightlen) <= 1&&isBalanced(root.left) && isBalanced(root.right);
}
/**
* 获取二叉树的高度----->最大深度
*
* @param root
* @return
*/
public int getLength(TreeNode root) {
if (root == null) {
return 0;
}
return 1 + Math.max(getLength(root.left), getLength(root.right));
}
}
自底向上的递归:避免了重复计算height,(后序遍历) 时间复杂度:O(n)
自底向上递归的做法类似于后序遍历,对于当前遍历到的节点,先递归地判断其左右子树是否平衡,再判断以当前节点为根的子树是否平衡。如果一棵子树是平衡的,则返回其高度(高度一定是非负整数),否则返回 -1−1。如果存在一棵子树不平衡,则整个二叉树一定不平衡。
注意:短路或的优化,先判断左子树是不是平衡的,要是左子树不是平衡的也没必要去判断右子树是否平衡
class Solution {
/**
* 判断是否为平衡二叉树---->自底向上
*
* @param root
* @return
*/
public boolean isBalanced(TreeNode root) {
return getLength(root) >= 0;
}
/**
* 获取高度---->自底向上完全是平衡二叉树,最后可以获得树的高度,但是如果有一个结点不是,直接断掉
*
* @param root
* @return
*/
public int getLength(TreeNode root) {
if (root == null) {
return 0;
}
int leftLength = getLength(root.left);
int rightLength = getLength(root.right);
if (leftLength == -1 || rightLength == -1 || Math.abs(leftLength - rightLength) > 1) {
return -1;
}
return 1 + Math.max(leftLength, rightLength);
}
}
* 257.二叉树的所有路径
递归形式返回二叉树中的所有路径,采用前序遍历,需要利用到回溯。
class Solution {
/**
* 二叉树的所有路径---->以list方式返回(递归)
*
* @param root
* @return
*/
public List<String> binaryTreePaths(TreeNode root) {
List<String> ans = new ArrayList<>();
if (root == null) {
return ans;
}
List<Integer> paths = new ArrayList<>();
travesal(root, paths, ans);
return ans;
}
/**
* 递归
*/
public void travesal(TreeNode root, List<Integer> paths, List<String> ans) {
paths.add(root.val);
//是叶子结点
if (root.left == null && root.right == null) {
//加入结果集,比如 1->3->7->9
StringBuffer sb = new StringBuffer();
for (int i = 0; i < paths.size() - 1; i++) {
sb.append(paths.get(i));
sb.append("->");
}
sb.append(paths.get(paths.size() - 1));
ans.add(sb.toString());
}
if (root.left != null) {
travesal(root.left, paths, ans);
paths.remove(paths.size() - 1);//回溯
}
if (root.right != null) {
travesal(root.right, paths, ans);
paths.remove(paths.size() - 1);
}
}
}
注重递归运行的顺序
404.左叶子之和
返回二叉树的所有左叶子之和,左叶子首先是叶子结点,再是父节点的左孩子
节点A的左孩子不为空,且左孩子的左右孩子都为空(说明是叶子节点),那么A节点的左孩子为左叶子节点
所以判断当前节点是不是左叶子是无法判断的,必须要通过节点的父节点来判断其左孩子是不是左叶子。
递归的遍历顺序为后序遍历(左右中),是因为要通过递归函数的返回值来累加求取左叶子数值之和。
class Solution {
/**
* 求解二叉树的左子树之和
*
* @param root
* @return
*/
public int sumOfLeftLeaves(TreeNode root) {
if (root == null) {
return 0;
}
int leftLeaf = sumOfLeftLeaves(root.left);
int rightLeaf = sumOfLeftLeaves(root.right);
int temp = 0;
if (root.left != null && root.left.left == null && root.left.right == null) {//找到左叶子
temp = root.left.val;
}
return temp + leftLeaf + rightLeaf;
}
}
注意leftLeaf和rightLeaf的位置,以及进行递归的方法。
2022.11.23补