https://leetcode.com/problems/balanced-binary-tree/
由于平衡二叉树的定义,很容易想到这题是计算树的最大深度的扩展。思路1:计算节点的左子树和右子树的最大深度,如果该节点的左右子树的深度超过1,则不是平衡二叉树;如果<=1,则需要再次递归遍历其后代节点;
实现代码如下:
public boolean isBalanced(TreeNode root) {
if (root == null) return true;
int l = maxDepth(root.left);
int r = maxDepth(root.right);
if (Math.abs(l - r) > 1) {
return false;
}
return isBalanced(root.left) && isBalanced(root.right);
}
private int maxDepth(TreeNode root) {
if (root == null) return 0;
int l = maxDepth(root.left);
int r = maxDepth(root.right);
return 1 + Math.max(l, r);
}
很容易看到,计算root的left和right子树时,每个节点的最大深度值都计算了一次,另外,如果某个节点已经计算出速度差>=1,表示该树不是平衡二叉树,程序并没返回,还在计算。其实不需要每次递归都计算每个节点的深度。也就是说,可以有一种算法,每个节点只遍历一次,即O(n)的时间复杂度内就可以算出结果。
可以定义一个全局变量,表示该二叉树是否为平衡二叉树。计算maxDepth的时候,如果某个节点的速度差>1,直接返回false。最多遍历一次全树,就可以返回这个结果值。
代码如下:
class Solution {
private boolean res = true;
public boolean isBalanced(TreeNode root) {
maxDepth(root);
return res;
}
public int maxDepth(TreeNode root) {
if (!res || root == null) return 0; // 注意这个地方,如果res为false,可以直接就返回,表示当前的二叉树已经不是一颗平衡二叉树。
int left = maxDepth(root.left);
int right = maxDepth(root.right);
if (Math.abs(left - right) > 1)
res = false;
return Math.max(left, right) + 1;
}
}
还有网上的解法,和上述类似,depth计算深度时,如果不是平衡二叉树,返回-1.
public boolean isBalanced(TreeNode root) {
return depth(root) != -1;
}
private int depth(TreeNode root) {
if (root == null) return 0;
int l = depth(root.left);
if (l == -1) return -1;
int r = depth(root.right);
if (r == -1) return -1;
if (Math.abs(l - r) > 1) return -1;
else return Math.max(depth(root.left), depth(root.right)) + 1;
}