Binary trees are fundamental data structures in computer science that appear frequently in coding interviews and real-world applications. This guide offers a straightforward explanation of binary trees, their implementation in Python, and common problem-solving patterns.
What is a Binary Tree?
A binary tree is a hierarchical data structure where each node has at most two children, referred to as the left child and right child. Key characteristics include:
- Every node contains a value and references to its children (if any)
- There is exactly one root node (the topmost node)
- Nodes with no children are called leaf nodes
- The structure naturally represents hierarchical relationships
- Binary trees enable efficient searching, insertion, and deletion operations
Python Implementation and Basic Operations
Node Structure
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val # Node value
self.left = left # Left child reference
self.right = right # Right child reference
Creating a Binary Tree
def create_binary_tree():
# Create a simple binary tree
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
return root
Basic Operations (for Binary Search Trees)
def insert(root, val):
"""Insert a value into a binary search tree"""
if not root:
return TreeNode(val)
if val < root.val:
root.left = insert(root.left, val)
else:
root.right = insert(root.right, val)
return root
def search(root, val):
"""Search for a value in a binary search tree"""
if not root or root.val == val:
return root
if val < root.val:
return search(root.left, val)
else:
return search(root.right, val)
Binary Tree Traversals
There are four primary ways to traverse a binary tree, each visiting nodes in a different order:
1. Pre-order Traversal (Root → Left → Right)
def preorder_traversal(root):
result = []
def dfs(node):
if not node:
return
result.append(node.val) # Visit root first
dfs(node.left) # Then left subtree
dfs(node.right) # Finally right subtree
dfs(root)
return result
2. In-order Traversal (Left → Root → Right)
def inorder_traversal(root):
result = []
def dfs(node):
if not node:
return
dfs(node.left) # Visit left subtree first
result.append(node.val) # Then root
dfs(node.right) # Finally right subtree
dfs(root)
return result
3. Post-order Traversal (Left → Right → Root)
def postorder_traversal(root):
result = []
def dfs(node):
if not node:
return
dfs(node.left) # Visit left subtree first
dfs(node.right) # Then right subtree
result.append(node.val) # Finally root
dfs(root)
return result
4. Level-order Traversal (Breadth-First)
from collections import deque
def level_order_traversal(root):
if not root:
return []
result = []
queue = deque([root])
while queue:
level_size = len(queue)
level = []
for _ in range(level_size):
node = queue.popleft()
level.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(level)
return result
Common LeetCode Binary Tree Problem Categories
Binary tree problems on LeetCode can generally be classified into these categories:
1. Traversal Problems
- Implementing various traversal methods
- Serializing and deserializing binary trees
- Reconstructing binary trees from traversal results
2. Path Sum Problems
- Determining if a path with a target sum exists
- Finding maximum path sum
- Calculating sum of all paths
3. Structure-related Problems
- Finding maximum/minimum depth
- Validating balanced binary trees
- Checking if a tree is symmetric
- Determining if two trees are identical
4. Binary Search Tree (BST) Problems
- Validating a BST
- Implementing BST operations (insert, delete)
- Finding kth smallest element
- Converting BST to greater sum tree
5. Tree Transformation Problems
- Flattening binary tree to linked list
- Converting sorted array to balanced BST
- Creating mirror/inverted binary tree
Conclusion
Binary trees are versatile data structures that form the foundation for more complex tree variants like AVL trees, Red-Black trees, and B-trees. Understanding the core concepts and traversal patterns presented here will equip you with the knowledge to tackle a wide range of tree-based problems in both interviews and real-world applications.
By mastering these fundamentals, you’ll be better prepared to recognize problem patterns and apply efficient tree-based solutions in your programming journey.