leetcode:判斷一棵樹是否爲平衡二叉樹

題目來源:力扣

題目要求:

輸入一棵二叉樹的根節點,判斷該樹是不是平衡二叉樹。如果某二叉樹中任意節點的左右子樹的深度相差不超過1,那麼它就是一棵平衡二叉樹。

審題:

題目要求很簡單,判斷一棵樹是否爲平衡二叉樹.根據平衡二叉樹的定義,我們可以得出一棵平衡樹的所有子節點構成的子樹也一定爲平衡樹.這種遞歸的定義指引我們使用遞歸的方式來判斷一棵樹是否是平衡二叉樹.
我們可以使用如下思路判斷:如果以當前節點爲根的子樹不是平衡二叉樹,則當前樹一定不是平衡二叉樹.否則,我們需要計算判斷其左子樹與右子樹是否爲平衡二叉樹,如果其中之一不是,則當前子樹不是平衡二叉樹.否則繼續遞歸檢查,直至底層.我們知道判斷一棵樹是否是平衡二叉樹需要我們分別計算左子樹高度與右子樹高度,而這種自頂向上的遞歸方式中,我們在計算所有節點樹高的過程中,存在大量的重複計算.因爲每一個節點會在其上所有祖宗節點的高度計算中,多次重複計算其自身高度.看到這裏,可能有人想到了計算原文題與子問題的求解中存在重複的計算部分,那麼是不是要用動態規劃了?其實大可不必,我們仔細分析便可發現,如果我們採用自底向上的思路,則不用動態規劃便可輕鬆解決.因爲使用自底向上的思路,我們相當於對節點進行後序遍歷,所有節點僅需計算一次其樹高,不存在重複計算的問題.自底向上判斷平衡二叉樹與自頂向下一致,如果以當前節點爲根的子樹不是平衡二叉樹,則該樹不是平衡二叉樹.否則我們向上檢查其父節點是否平衡二叉樹.

回顧一下我們的分析過程:

  • 我們首先根據平衡二叉樹的遞歸定義得出,要判斷一棵樹是否是平衡的,可以採用遞歸的方法
  • 我們發現,當使用先序遍歷方式檢查每一節點是否是平衡子樹時,對各節點樹高的計算中存在大量重複計算.
  • 使用後序遍歷方式檢查每一節點是否是平衡子樹時,不存在對樹高的重複計算,每一節點僅需計算一次樹高.

因此我們使用後序遍歷方式檢查每一節點,判斷當前樹是否是平衡樹.如果發現任意節點不平衡,則其後遞歸直接返回即可.

java算法實現:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    boolean balanced = true;
    //遍歷每一子節點,檢查以當前子節點爲根的樹是否爲平衡樹,如果發現某一子樹不平衡,則該棵樹不平衡;
    //時間複雜度O(N),需要遍歷每一個子節點
    //空間複雜度爲樹的最大深度,當樹平衡時,爲O(lgN),最壞情況下,爲O(N)
    private int depth(TreeNode x){
        if(x == null || !balanced) //如果balance爲false, 則後續直接返回
            return 0;
        int depthLeft = depth(x.left);
        int depthRight = depth(x.right);
        if(Math.abs(depthLeft-depthRight) > 1)
            balanced = false;
        return Math.max(depthLeft, depthRight) + 1;
    }

    public boolean isBalanced(TreeNode root) {
        depth(root);
        return balanced;
    }
}

在上面的實現中,我們使用額外的boolean變量balanced紀錄當前是否發現不平衡子樹,在參考其他大佬的題解中,發現可是省略這一布爾變量,由於樹的高度不會小於0,因此我們可以返回-1表示當前子樹不平衡,如果當前節點的任意子樹高度爲-1,則該樹的高度也爲-1.

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private int depth(TreeNode x){
        if(x == null)
            return 0;
        int depthLeft = depth(x.left);
        if(depthLeft == -1)
            return -1;
        int depthRight = depth(x.right);
        if(depthRight == -1)
            return -1;

        if(Math.abs(depthLeft-depthRight) > 1) //如果樹不平衡,我們返回-1作爲樹高.
            return -1;
        else
            return Math.max(depthLeft, depthRight) + 1;
    }

    public boolean isBalanced(TreeNode root) {
        return depth(root) != -1;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章