Home Binary Tree Level Order Traversal
Post
Cancel

Binary Tree Level Order Traversal

Links

Go to my solution
Go to the question on LeetCode

My Thoughts

What Went Well
I implemented my solution quickly and had a very good runtime, and after optimizing, I got an outstanding space complexity.

What I Learned
I learned how to convert my program into a more optimal solution using the breadth first search algorithm. I also learned that the len() function is an O(1) operation and not O(n). This was nice to know since I have avoided some solutions because of this belief.

How I Can Improve
By practicing the implementation of depth and breadth-first search, I can master two very commonly used algorithms for trees and graphs.

Algorithm Description

Binary Tree - A rooted tree where every node has at most two children, the left and right children.

Depth-First Search - An algorithm for traversing a tree data structure. The algorithm begins at the root node and searches until it can not continue any deeper. Once at the deepest point, the algorithm works backward until all the nodes have been visited.

Breadth-first search - A tree/matrix traversal algorithm that searches for elements with a given property. It creates a deque of elements yet to be visited and then iterates through each level (similar properties) until there are no more elements to iterate through. In this example, the similar property would be equal depths in the tree.

The proper definition for breadth-first search when not being applied to this specific problem can be found here.

Visual Examples
Binary Tree, click to view

Depth-first search being performed on a tree, click to view

Solution Statistics For Breadth-First Search

Time Spent Optimizing
5 minutes

Time Complexity
O(n) - Each node (n) must pass through the while loop, and since the while loop is an O(1) block of code, we get an O(n) time complexity.

Space Complexity
O(n) - We are constantly pushing and popping off the deque but only appending to the sorted list. The number of elements in the sorted list exceeds that of the deque, resulting in the O(n) space complexity.

Runtime Beats
89.74% of other submissions

Memory Beats
97.74% of other sumbissions

Optimal Solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        if root is None: return []  # O(1)

        order = []  # O(1)
        q = deque() # O(1)
        q.append((root,0))  # O(1)

	# Continuously iterate through the deque until it is empty
        while q:
            cur, depth = q.popleft()    # O(1)
            
            if depth == len(order):     # O(1)
                order.append([cur.val]) # O(1)
            else:
                order[depth].append(cur.val)    # O(1)

            if cur.left: q.append((cur.left,depth+1))   # O(1)
            if cur.right: q.append((cur.right,depth+1)) # O(1)
        
        return order

Solution Statistics For Depth First Search

Time Spent Coding
15 minutes

Time Complexity
O(n) - Each node (n) must call the search function, and the search function is an O(1) time complexity function, resulting in the O(n) space complexity.

Space Complexity
O(n) - Each node must be stored in the sorted list, resulting in the O(n) space complexity. Truly the space complexity is O(n + log n). The log n is for the most amount of possible recursive calls yet to be completed.

Runtime Beats
91.90% of other submissions

Memory Beats
16.32% of other sumbissions

Solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 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 levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        if root is None: return []  # O(1)

        self.order = []     # O(1)

        def search(root,depth):
            
            # If the length of the ordered list is equal to the depth,
            # then that depth has not been visited yet, so append it
            # with the given element
            if len(self.order) == depth:    # O(1)
                self.order.append([root.val])   # O(1)

            # If the length != the length, then append the current element
            # to the index of the depth
            else:
                self.order[depth].append(root.val)  # O(1)

            # Only call the search function if the node != None
            if root.left: search(root.left,depth+1)     # O(1)
            if root.right: search(root.right,depth+1)   # O(1)

        Search(root,0)  # O(n)
        return self.order
This post is licensed under CC BY 4.0 by the author.

K Closest Points to Origin

Clone Graph