110.Balanced Binary Tree從8ms到2ms到1ms
阿新 • • 發佈:2019-02-05
在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;
}
}