Problem Statement
Given a binary tree, perform a level order traversal. In level order traversal, the nodes are visited level by level from left to right.
Examples
Example 1:
Consider the following binary tree:
1
/ \
2 3
/ \
4 5
The level order traversal of the above tree is:
1, 2, 3, 4, 5
Explanation:
1 (because 1 is at level 1)
2, 3 (2, 3, is at same level)
4, 5 (4, 5 is at same level)
Different Approach
1️⃣ Queue Based Approach
Intuition:
To traverse a binary tree level by level and capture the values of nodes at each level, we use a method known as level-order traversal. This approach involves examining nodes one level at a time, starting from the root and moving downward through the tree. By using a queue to keep track of nodes at each level, we ensure that nodes are processed in the order they appear at each level. This method efficiently organizes nodes into a 2D structure where each sub-array represents a level of the tree, capturing the complete structure of the tree from top to bottom.
Approach:
To perform a level-order traversal iteratively, follow these steps:
- Start by initializing an empty queue to hold nodes as we traverse the tree level by level.
- Enqueue the root node into the queue. If the tree is empty, return an empty 2D vector immediately.
- While the queue is not empty, process each level of the tree:
- Determine the number of nodes at the current level by checking the size of the queue.
- Create a temporary vector to store the values of nodes at this level.
- For each node at the current level:
- Dequeue the front node from the queue.
- Store the node’s value in the temporary vector.
- Enqueue the left and right children of the current node (if they exist) into the queue.
- After processing all nodes at the current level, add the temporary vector to the final 2D vector representing the level order traversal.
- Once all levels are processed, return the 2D vector containing the level-order traversal of the binary tree.
Code:
#include <bits/stdc++.h>
using namespace std;
// Definition for a binary tree node.
struct TreeNode {
int data;
TreeNode* left;
TreeNode* right;
// Constructor with a value parameter for TreeNode
TreeNode(int val) : data(val), left(nullptr), right(nullptr) {}
};
class Solution {
public:
// Function to perform level-order traversal of a binary tree
vector<vector<int>> levelOrder(TreeNode* root) {
// Create a 2D vector to store levels
vector<vector<int>> ans;
if (root == nullptr) {
// If the tree is empty, return an empty vector
return ans;
}
// Create a queue to store nodes for level-order traversal
queue<TreeNode*> q;
// Push the root node to the queue
q.push(root);
while (!q.empty()) {
// Get the size of the current level
int size = q.size();
// Create a vector to store nodes at the current level
vector<int> level;
for (int i = 0; i < size; i++) {
// Get the front node in the queue
TreeNode* node = q.front();
// Remove the front node from the queue
q.pop();
// Store the node value in the current level vector
level.push_back(node->data);
// Enqueue the child nodes if they exist
if (node->left != nullptr) {
q.push(node->left);
}
if (node->right != nullptr) {
q.push(node->right);
}
}
// Store the current level in the answer vector
ans.push_back(level);
}
// Return the level-order traversal of the tree
return ans;
}
};
// Function to print the elements of a vector
void printVector(const vector<int>& vec) {
// Iterate through the vector and print each element
for (int num : vec) {
cout << num << " ";
}
cout << endl;
}
// Main function
int main() {
// Creating a sample binary tree
TreeNode* root = new TreeNode(1);
root->left = new TreeNode(2);
root->right = new TreeNode(3);
root->left->left = new TreeNode(4);
root->left->right = new TreeNode(5);
// Create an instance of the Solution class
Solution solution;
// Perform level-order traversal
vector<vector<int>> result = solution.levelOrder(root);
cout << "Level Order Traversal of Tree: "<< endl;
// Printing the level order traversal result
for (const vector<int>& level : result) {
printVector(level);
}
return 0;
}
Complexity Analysis:
- Time Complexity:
O(N)
whereN
is the number of nodes in the binary tree. Each node of the binary tree is enqueued and dequeued exactly once, hence all nodes need to be processed and visited. Processing each node takes constant time operations which contributes to the overall linear time complexity. - Space Complexity:
O(N)
whereN
is the number of nodes in the binary tree. In the worst case, the queue has to hold all the nodes of the last level of the binary tree; the last level could at most hold N/2 nodes, hence the space complexity of the queue is proportional to O(N). The resultant vector answer also stores the values of the nodes level by level and hence contains all the nodes of the tree contributing to O(N) space as well.