問題描述
輸入一棵二叉樹的根節點,判斷該樹是不是平衡二叉樹。
平衡二叉樹(Balanced Binary Tree):它是一棵空樹或它的左右兩個子樹的高度差的絕對值不超過1,並且左右兩個子樹都是一棵平衡二叉樹。
示例:
輸入:給定二叉樹 [3,9,20,null,null,15,7]
3
/ \
9 20
/ \
15 7
輸出:true
分析問題
平衡二叉樹是指二叉樹的每個節點的左右子樹的高度差的絕對值不超過1。根據定義,一顆二叉樹是平衡二叉樹,當且僅當它的所有子樹也是平衡二叉樹,所以,我們可以使用遞迴的方式來求解,我們根據遞迴的順序不同,可以分為自頂向下和自底向上兩種方式。
自頂向下方式(先序遍歷+判斷)
首先我們定義一個函式height,用來計算二叉樹中任意一個節點的高度。然後通過先序遍歷二叉樹,對於當前遍歷到的節點,我們首先計算其左子樹和右子樹的高度,然後判斷其左右子樹的高度差是否小於1,如果小於1,代表以該節點為根節點的二叉樹是平衡二叉樹,然後再分別遞迴地遍歷左右節點,並判斷左子樹和右子樹是否平衡。這是一個自頂向下的過程。如果所有子樹都平衡,代表該樹是一顆平衡二叉樹。
我們來看一下程式碼實現。
class Solution:
def IsBalanced_Solution(self, pRoot):
#求二叉樹的高度
def height(root):
if not root:
return 0
return max(height(root.left), height(root.right)) + 1
#如果數為空,代表是平衡二叉樹,直接返回
if not pRoot:
return True
#左子樹的高度
leftheight=height(pRoot.left)
#右子樹的高度
rightheight=height(pRoot.right)
#代表以該節點為根節點的二叉樹是平衡的
if abs(leftheight-rightheight) <=1:
#再遞迴判斷其左右子樹是否是平衡的
return self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right)
return False
自底向上的遞迴
在上面的演算法中,我們可以發現對於同一個節點,函式height會被重複呼叫,導致執行效率不高,如果採用自底向上的解法,對於每個節點,函式height只會被呼叫一次。
自底向上的遞迴是指,我們對二叉樹進行後序遍歷,對於當前遍歷到的節點,我們先遞迴的去判斷其左、右子樹是否是平衡的,然後再判斷以當前節點為根的二叉樹是否是平衡的。如果一棵子樹是平衡的,則返回其高度,否則返回 -1。如果存在一棵子樹不平衡,則整個二叉樹一定是不平衡。
下面我們來看一下程式碼實現。
class Solution:
def IsBalanced_Solution(self, pRoot):
#遞迴的求樹的高度
def height(root):
if not root:
return 0
#左子樹的高度
left_height= height(root.left)
#右子樹的高度
right_height = height(root.right)
#子樹的高度為-1,代表子樹不是平衡二叉樹,那麼該樹也不是平衡二叉樹,返回-1
#abs(leftHeight - rightHeight) > 1 代表左右子樹的高度差大於1,表示該樹是不平衡的,返回-1
if left_height == -1 or right_height == -1 or abs(left_height - right_height) > 1:
return -1
else:
#否則,返回樹的高度
return max(left_height, right_height) + 1
#如果樹的高度不是-1,代表該樹是平衡二叉樹
return height(pRoot) >= 0
該演算法的時間複雜度是O(N),空間複雜度也是O(N)。
最後
送大家幾本比較不錯的演算法書籍~
小爭哥資料結構與演算法
連結:https://pan.baidu.com/s/19Jk_G_-QTnGb3GRyzbENgA
密碼:keis
谷歌大佬LeetCode刷題指南
連結:https://pan.baidu.com/s/1vtRIsVltTxmIioqqkeSS5g
密碼:r3xg
演算法小抄
連結:https://pan.baidu.com/s/1rU_T6GRZ-WmV9QFmnJfCBg
密碼:unh5
更多有趣內容,請掃碼關注一波~