1. 程式人生 > 實用技巧 >LeetCode 110. 平衡二叉樹 | Python

LeetCode 110. 平衡二叉樹 | Python

110. 平衡二叉樹


題目來源:力扣(LeetCode)https://leetcode-cn.com/problems/balanced-binary-tree

題目


給定一個二叉樹,判斷它是否是高度平衡的二叉樹。

本題中,一棵高度平衡二叉樹定義為:

一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過1。

示例 1:

給定二叉樹 [3,9,20,null,null,15,7]

    3
   / \
  9  20
    /  \
   15   7
返回 true 。

示例 2:

給定二叉樹 [1,2,2,3,3,null,null,4,4]

       1
      / \
     2   2
    / \
   3   3
  / \
 4   4
返回 false 。

解題思路


思路:遞迴(自頂向下,自底向上)

審題,題目要求給定的二叉樹是否是高度平衡二叉樹。關於高度平衡二叉樹,題目給的定義是:一個二叉樹每個節點的左右兩個子樹的高度差的絕對值不超過 1。

也就是說,只有所有子樹都是平衡二叉樹的條件下,整個二叉樹才是平衡二叉樹。那麼我們用遞迴的思想來解決這個問題。

遞迴(自頂向下)

在這裡,我們先用自頂向下的思路來去解決這個問題。

上面說了,要判斷一個二叉樹是否是平衡二叉樹?要看所有子樹是否都是平衡二叉樹,那麼這裡需要比較每個節點左右子樹的高度差絕對值,不能超過 1。

那麼,首先考慮計算節點的高度 height,會有以下情況:

  • 若當前節點為空節點,那麼返回高度 0;
  • 若當前節點為非空節點,那麼這裡返回左右子樹中的最大高度 + 1。

然後,要考慮的是如何去判斷是否平衡?情況如下:

  • 先處理特殊情況,如果根節點為空,直接返回 True;
  • 根節點非空,那麼這裡用先序遍歷遞迴,對下面三種情況進行判斷:
    • 判斷當前子樹是否是平衡二叉樹;
    • 判斷當前子樹的左子樹是否是平衡二叉樹;
    • 判斷當前子樹的右子樹是否是平衡二叉樹。

具體的程式碼見【程式碼實現 # 遞迴(自頂向下)】

遞迴(自底向上)

在上面 遞迴(自頂向下) 的方法中,會產生大量重複計算,時間複雜度較高。

這裡具體的做法如下:

  • 設定終止條件:
    • 越過葉子節點時,返回高度 0;
    • 若左右子樹任一高度為 -1 的情況下,代表左右子樹不平衡,直接返回 -1。(這裡左右子樹高度由下面的左右子樹高度差絕對值是否超過 1 決定)
  • 如果當前節點左右子樹的高度差的絕對值不超過 1 時,那麼返回左右子樹最大高度 +1;
  • 如果當前節點左右子樹的高度差的絕對值超過 1 時,返回 -1,表示子樹不平衡。

具體的程式碼見【程式碼實現 # 遞迴(自底向上)】

程式碼實現


# 遞迴(自頂向下)
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        def depth(root):
            """求當前節點的深度
            Args:
                root: 節點
            Returns:
                返回節點深度
            """
            # 節點為空,返回高度 0
            if not root:
                return 0
            # 否則返回左右子樹最大高度值 +1
            return max(depth(root.left), depth(root.right)) + 1

        # 根節點為空,直接返回 True
        if not root:
            return True

        # 否則遞迴判斷
        # 1. 當前子樹是否平衡
        # 2. 當前子樹左子樹是否平衡
        # 3. 當前子樹右子樹是否平衡
        return abs(depth(root.left)-depth(root.right)) <= 1 and self.isBalanced(root.left) and self.isBalanced(root.right)

# 遞迴(自底向上)
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        def helper(root):
            if not root:
                return 0
            left = helper(root.left)
            # 當左右子樹高度為 -1,表示不平衡返回 -1
            if left == -1:
                return -1
            right = helper(root.right)
            if right == -1:
                return -1
            
            # 判斷左右子樹高度差的絕對值是否不超過 1
            return -1 if abs(left-right) > 1 else max(left, right) + 1
        
        return helper(root) >= 0

實現結果


歡迎關注


公眾號 【書所集錄