1. 程式人生 > >110.Balanced Binary Tree從8ms到2ms到1ms

110.Balanced Binary Tree從8ms到2ms到1ms

在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;
    }
}