Teaching Kids Programming – Top Down and Bottom Up Recursive Algorithms to Determine a Balanced Binary Tree


Teaching Kids Programming: Videos on Data Structures and Algorithms

Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary tree is defined as: a binary tree in which the left and right subtrees of every node differ in height by no more than 1.

Example 1:
Input: root = [3,9,20,null,null,15,7]
Output: true

Example 2:
Input: root = [1,2,2,3,3,null,null,4,4]
Output: false

Example 3:
Input: root = []
Output: true

balanced-binary-tree Teaching Kids Programming - Top Down and Bottom Up Recursive Algorithms to Determine a Balanced Binary Tree algorithms python recursive teaching kids programming youtube video

Top Down Recursive Algorithm to Determine a Balanced Binary Tree

We know the Recursive Algorithm to Compute the depth for a given binary tree in O(N) time:

1
2
3
4
5
6
def depth(root):
   if not root:
       return 0
   left = depth(root.left)
   right = depth(root.right)
   return max(left, right) + 1
def depth(root):
   if not root:
       return 0
   left = depth(root.left)
   right = depth(root.right)
   return max(left, right) + 1

A Binary Tree is balanced as long as its left tree and right tree are also balanced (for every node, in recursive definition), also the depth of the left sub tree and right sub tree is no more than 1 (also needs to be satisfied in recursive manner).

1
2
3
4
5
6
7
8
9
10
11
12
# Definition for a binary tree node
# class TreeNode
#     def _init_(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        if root is None:
            return True
        return self.isBalanced(root.left) and self.isBalanced(root.right) and \
                abs(depth(root.left) - depth(root.right)) <= 1
# Definition for a binary tree node
# class TreeNode
#     def _init_(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        if root is None:
            return True
        return self.isBalanced(root.left) and self.isBalanced(root.right) and \
                abs(depth(root.left) - depth(root.right)) <= 1

However, the time complexity is O(NLogN) not optimial.

Bottom Up Algorithm to Check Balanced Binary Tree

Based on the Recursive Depth Function, we know the heights of a node’s left and right subtree, then we can invalidate the result once we find the difference is more than 1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Definition for a binary tree node
# class TreeNode
#     def _init_(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        self.ans = True
        def depth(root):
            if not root:
                return 0
            left = depth(root.left)
            right = depth(root.right)
            if abs(left - right) > 1:
                self.ans = False
            return max(left, right) + 1
        depth(root)
        return self.ans
# Definition for a binary tree node
# class TreeNode
#     def _init_(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        self.ans = True
        def depth(root):
            if not root:
                return 0
            left = depth(root.left)
            right = depth(root.right)
            if abs(left - right) > 1:
                self.ans = False
            return max(left, right) + 1
        depth(root)
        return self.ans

The time complexity is the same as getting the height of a binary tree. We can also return a tuple where the first value indicates if the current tree is balanced, and the second value is the height of the tree. The time complexity is O(N).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Definition for a binary tree node
# class TreeNode
#     def _init_(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        if root is None:
            return True
        def depth(root):
            if not root:
                return True, 0
            leftBalanced, left = depth(root.left)
            if not leftBalanced:
                return False, 0
            rightBalanced, right = depth(root.right)
            if not rightBalanced:
                return False, 0
            return abs(left - right) <= 1, max(left, right) + 1
        return depth(root)[0]
# Definition for a binary tree node
# class TreeNode
#     def _init_(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        if root is None:
            return True
        def depth(root):
            if not root:
                return True, 0
            leftBalanced, left = depth(root.left)
            if not leftBalanced:
                return False, 0
            rightBalanced, right = depth(root.right)
            if not rightBalanced:
                return False, 0
            return abs(left - right) <= 1, max(left, right) + 1
        return depth(root)[0]

–EOF (The Ultimate Computing & Technology Blog) —

GD Star Rating
loading...
671 words
Last Post: Teaching Kids Programming - Index with Equal Left and Right Sums (Prefix and Suffix Sum Algorithm)
Next Post: Teaching Kids Programming - Estimate the Math Continued Fraction Value in Python (Recursion and Iterative Algorithm)

The Permanent URL is: Teaching Kids Programming – Top Down and Bottom Up Recursive Algorithms to Determine a Balanced Binary Tree

Leave a Reply