在leetcode上面刷了道题,最开始用时8ms,改进后用时2ms,再改用时1ms,下面记录一下:
题目:
Given a binary tree, determine if it is height-balanced.
For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.
简单地说,对于给定的一棵二叉树,判断它是否是平衡二叉树
8ms解法:
- 容易想见,如果一棵树是平衡二叉树,那么它的左右子树高度差不超过1
而且,如果一棵树是平衡二叉树,那么它的任一子树也是平衡二叉树
于是,可以这样做:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public boolean isBalanced(TreeNode root) {
if (root == null) {
return true;
}
return isBalanced(root.left) && isBalanced(root.right) && depth(root.left) - depth(root.right) >= -1 && depth(root.left) - depth(root.right) <= 1;
}
private int depth(TreeNode root) {
// TODO Auto-generated method stub
if (root == null) {
return 0;
}
return 1 + (depth(root.left) > depth(root.right) ? depth(root.left) : depth(root.right));
}
}
2ms解法
- 在上面的解法中,我们发现了一个问题,每次判断一个子树是否是平衡二叉树的时候,我们都要对它的左右子树求高度,也就是说,如果一个结点在这棵二叉树的k棵子树中出现过,那么要计算以这个结点为根节点的子树的高度k次,显然大大增加了时间开销。
- 于是我利用了树结点中的value去记录以该结点为根节点的子树的高度,那么,当求一棵子树的高度时,可以先求根结点的左右子树的高度,之后将1+max(左子树高度,右子树高度)作为这棵子树的高度。
代码如下:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public boolean isBalanced(TreeNode root) {
if (root == null) {
return true;
}
root = getDepth(root);
return isBalanceCore(root);
}
private boolean isBalanceCore(TreeNode root) {
// TODO Auto-generated method stub
if (root == null) {
return true;
}
if (root.left == null && root.right == null) {
return true;
}
if (root.left != null && root.right == null) {
if (root.left.left == null && root.left.right == null) {
return true;
}
return false;
}
if (root.left == null && root.right != null) {
if (root.right.left == null && root.right.right == null) {
return true;
}
return false;
}
return isBalanceCore(root.left) && isBalanceCore(root.right) && root.left.val - root.right.val >= -1 && root.left.val - root.right.val <= 1;
}
private TreeNode getDepth(TreeNode root) {
// TODO Auto-generated method stub
if (root.left == null && root.right == null) {
root.val = 1;
}else if (root.left != null && root.right == null) {
root.left = getDepth(root.left);
root.val = 1 + root.left.val;
}else if (root.left == null && root.right != null) {
root.right = getDepth(root.right);
root.val = 1 + root.right.val;
}else {
root.left = getDepth(root.left);
root.right = getDepth(root.right);
root.val = 1 + (root.left.val > root.right.val ? root.left.val : root.right.val);
}
return root;
}
}
1ms解法
其实原本这篇博客的题目是从8ms到2ms,就在刚刚写到2ms解法的时候,突然想起来,反正我都要计算树中每个结点为根结点的子树的高度,那么为什么不在计算高度的时候顺便判断一下是不是平衡二叉树呢?
- 这里我设置了一个全局变量isBalance并初始化为true,每次求完一个结点的value,我都判断一下以它为根的子树是否是平衡二叉树,如果不是,那么修改isBalance的值为false。这样,在对树中每个结点求value之后,就已经知道这棵树是否是平衡二叉树了
代码如下:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
boolean isBalance = true;
public boolean isBalanced(TreeNode root) {
if (root == null) {
return true;
}
root = getDepth(root);
return isBalance;
}
private TreeNode getDepth(TreeNode root) {
// TODO Auto-generated method stub
if (root.left == null && root.right == null) {
root.val = 1;
}else if (root.left != null && root.right == null) {
root.left = getDepth(root.left);
root.val = 1 + root.left.val;
if (root.left.val > 1) {
isBalance = false;
}
}else if (root.left == null && root.right != null) {
root.right = getDepth(root.right);
root.val = 1 + root.right.val;
if (root.right.val > 1) {
isBalance = false;
}
}else {
root.left = getDepth(root.left);
root.right = getDepth(root.right);
root.val = 1 + (root.left.val > root.right.val ? root.left.val : root.right.val);
if (root.left.val - root.right.val > 1 || root.left.val - root.right.val < -1) {
isBalance = false;
}
}
return root;
}
}