題目分析:
給定一個二叉樹,判斷它是否是高度平衡的二叉樹。本題中,一棵高度平衡二叉樹定義爲:一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過1。
示例 1:給定二叉樹 [3,9,20,null,null,15,7]
返回 true 。
示例 2:給定二叉樹 [1,2,2,3,3,null,null,4,4]
返回 false 。
解題思路:
思路一: 我們在【LeetCode】104. Maximum Depth of Binary Tree寫過計算二叉樹深度的代碼,我們可以使用那一題的代碼來計算每個節點左右的深度,然後做差判斷。
- 獲取節點深度函數(與【LeetCode】104. Maximum Depth of Binary Tree遞歸代碼相同)
def getDepth(self, root: TreeNode) -> int:
if not root: return 0
return 1 + max(self.getDepth(root.left), self.getDepth(root.right))
- 判斷根節點左右子樹深度差是否超過1,大於1就返回錯誤
if abs(self.getDepth(root.left) - self.getDepth(root.right)) > 1: return False
- 遞歸根節點的左右子樹
return self.isBalanced(root.left) and self.isBalanced(root.right)
思路二: 思路一簡單易懂,效率偏低的主要原因是,如下圖,首先會遞歸計算9與20的深度,然後又會遞歸計算已經算過的15和7的深度,也就是說它計算節點深度會把所有根節點全計算一遍。
改進思路一
- 我們每次計算節點深度同時判斷是否爲平衡樹,是的話就返回深度給上一層,否則返回-1
return (1 + max(left_depth, right_depth)) if abs(left_depth - right_depth) <= 1 else -1
- 然後如果節點值爲-1,代表該節點已經不爲平衡樹,我們就一直向上層返回-1
left_depth = self.dfs(root.left)
if left_depth == -1: return -1
right_depth = self.dfs(root.right)
if right_depth == -1: return -1
- 最外層函數接收到返回-1,就知道不是平衡樹了,這樣僅深度遞歸一次就解決了問題(有些節點沒有計算是小於等於一次的)
return self.dfs(root) != -1
提交代碼1:(簡單遞歸,Runtime: 76 ms, faster than 39.60% )
class Solution:
def isBalanced(self, root: TreeNode) -> bool:
if not root: return True
if abs(self.getDepth(root.left) - self.getDepth(root.right)) > 1: return False
return self.isBalanced(root.left) and self.isBalanced(root.right)
def getDepth(self, root: TreeNode) -> int:
if not root: return 0
return 1 + max(self.getDepth(root.left), self.getDepth(root.right))
提交代碼2:(同時計算深度與平衡樹的遞歸,時間複雜度O(N),Runtime: 48 ms, faster than 99.67% )
class Solution:
def isBalanced(self, root: TreeNode) -> bool:
return self.dfs(root) != -1
def dfs(self, root: TreeNode) -> int:
if not root: return True
left_depth = self.dfs(root.left)
if left_depth == -1: return -1
right_depth = self.dfs(root.right)
if right_depth == -1: return -1
return (1 + max(left_depth, right_depth)) if abs(left_depth - right_depth) <= 1 else -1