剑指 Offer 55 - II. 平衡二叉树 20200826

文章目录

  • 题目描述
  • 解法1:先序遍历判断各个子树是否为平衡树
    • 结果
  • 解法2 后序遍历 + 剪枝
    • 结果


题目描述

剑指 Offer 55 - II. 平衡二叉树
输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过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 <= 树的结点个数 <= 10000


解法1:先序遍历判断各个子树是否为平衡树

从树的根节点开始,计算其左右子树的深度,如果相差大于1,则返回False,否则继续递归判断其左右孩子结点。

时间复杂度:O( N log ⁡ N N\log N NlogN), N为树的结点个数,

最差情况下(为 “满二叉树” 时), isBalanced(root) 遍历树所有节点,判断每个节点的深度 depth(root) 需要遍历各子树的所有节点 。
满二叉树高度的复杂度 O( log ⁡ \log logN),将满二叉树按层分为 log ⁡ \log log (N+1) 层;通过调用 depth(root) ,判断二叉树各层的节点的对应子树的深度,需遍历节点数量为 N × 1 N \times 1 N×1, N − 1 2 × 2 \frac{N-1}{2} \times 2 2N1×2, N − 3 4 × 4 \frac{N-3}{4} \times 4 4N3×4, N − 7 8 × 8 \frac{N-7}{8} \times 8 8N7×8, …, 1 × N + 1 2 1 \times \frac{N+1}{2} 1×2N+1, 。因此各层执行 depth(root) 的时间复杂度为 O(N)(每层开始,最多遍历 N 个节点,最少遍历 N + 1 2 \frac{N+1}{2} 2N+1个节点)。
因此,总体时间复杂度 = 每层执行复杂度 × \times × 层数复杂度 = O ( N × l o g N ) O(N \times log N) O(N×logN)
作者:jyd
链接:https://leetcode-cn.com/problems/ping-heng-er-cha-shu-lcof/solution/mian-shi-ti-55-ii-ping-heng-er-cha-shu-cong-di-zhi/
来源:力扣(LeetCode)

空间复杂度:O(N), 最差情况下(树退化为链表时),系统递归需要使用 O(N)的栈空间。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def depth(self, root, d):
        # d >= 1
        if root is None:
            return d-1
        return max(self.depth(root.left, d+1), self.depth(root.right, d+1))
    def isBalanced(self, root):
        if root is not None:
            if abs(self.depth(root.left, 1)-self.depth(root.right, 1)) > 1:
                return False
            return self.isBalanced(root.left) and self.isBalanced(root.right)
        else:
            return True

结果

剑指 Offer 55 - II. 平衡二叉树 20200826_第1张图片
上述代码可优化为:

参考自 力扣解答方法2

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def depth(self, root, d):
            # d >= 1
            if root is None:
                return d-1
            return max(self.depth(root.left, d+1), self.depth(root.right, d+1))
    def isBalanced(self, root: TreeNode) -> bool:
        if root is not None:
            return abs(self.depth(root.left, 1)-self.depth(root.right, 1)) <= 1 and self.isBalanced(root.left) and self.isBalanced(root.right)
        else:
            return True

解法2 后序遍历 + 剪枝

参考自 力扣解答方法1

后序遍历首先判断左右子树是否为平衡树,然后再比较左右子树的深度,完成判断该树是否为平衡树。
定义recur(root)函数,用于计算以root为根节点的深度,当该树不是平衡树树返回-1:

  1. 如果root为None,返回0
  2. 如果root不为None,计算左子树的深度 l e f t left left,如果为-1则返回-1;
  3. 如果root不为None,计算右子树的深度 r i g h t right right,如果为-1则返回-1;
  4. 左右子树均为平衡树,如果 ∣ l e f t − r i g h t ∣ > 1 |left-right|>1 leftright>1,返回-1,否则返回 max ⁡ ( l e f t , r i g h t ) + 1 \max (left, right) + 1 max(left,right)+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 recur(root):
            if root is None:
                return 0
            left = recur(root.left)
            if -1 == left:
                return -1
            right = recur(root.right)
            if -1 == right:
                return -1
            return -1 if abs(left-right) > 1 else max(left, right) + 1
        return -1 != recur(root)

结果

剑指 Offer 55 - II. 平衡二叉树 20200826_第2张图片

时间复杂度:O(N), N为树的结点个数,最差情况下,每个结点需计算一次。
空间复杂度:O(N),最差情况下(树退化为链表时),系统递归需要使用 O(N)的栈空间。

你可能感兴趣的:(LeetCode,二叉树,leetcode)