Problem Statement
In this problem, you are supplied with the root node of a binary tree, and your task is to determine the maximum depth of that binary tree. The maximum depth is defined as the length of the longest path from the root node to the farthest leaf node. This is essentially the number of nodes that lie on the longest path from the root node to a leaf node in the binary tree. The problem involves understanding the structure of the binary tree from the given root and exploring each possible path to find the maximum length.
Examples
Example 1
Input:
root = [3,9,20,null,null,15,7]
Output:
3
Example 2
Input:
root = [1,null,2]
Output:
2
Constraints
- The number of nodes in the tree is in the range
[0, 104]
. -100 <= Node.val <= 100
Approach and Intuition
To solve the problem of finding the maximum depth of a binary tree, we can employ several intuitive approaches or methodologies:
Recursive Depth-First Search (DFS):
- Conceptually, the maximum depth of the tree is the greater depth between its left child and right child, plus one (for the root node itself).
- For an empty tree where the root is
None
, the depth is0
. - For other nodes, recursively find the depth of the left subtree and the right subtree, and add one to account for the root node at each step.
Example walkthrough:
For the tree
[3,9,20,null,null,15,7]
:- Starting at the root
3
, which has a left child9
(leaf node) and a right child20
. - The left child
9
contributes a depth of1
. - The right child
20
further expands to15
and7
, each contributing a depth of1
but since20
is not a leaf and has children, it adds additional depth making the total2
from node20
to its leaves. - Thus, adding one for the root
3
, the total maximum depth is3
.
- Starting at the root
Iterative Approach Using Queue:
- A level-order traversal can be used by employing a queue to track nodes across each level of the tree.
- Initialize a count for depth. For each level of nodes processed, increment the depth count.
- Push root into the queue, then continuously expand the queue by popping the front and pushing its children until the queue is empty.
Both methods ensure all nodes are visited, either recursively or iteratively, leading to a complete assessment of the tree's structure to determine its deepest path. The constraints allow significant flexibility in depth, so optimization in large structures becomes crucial, especially avoiding recursion depth limits and managing memory in breadth-first explorations.
Solutions
- C++
- Java
- C
- JavaScript
- Python
class Solution {
public:
int maximumDepth(TreeNode* node) {
if (node == NULL) {
return 0;
}
vector<pair<int, TreeNode*>> stack;
stack.push_back(make_pair(1, node));
int deepest = 0;
while (!stack.empty()) {
pair<int, TreeNode*> current = stack.back();
int currentDepth = current.first;
TreeNode* currentNode = current.second;
deepest = max(deepest, currentDepth);
stack.pop_back();
if (currentNode->left != NULL) {
stack.push_back(make_pair(currentDepth + 1, currentNode->left));
}
if (currentNode->right != NULL) {
stack.push_back(make_pair(currentDepth + 1, currentNode->right));
}
}
return deepest;
}
};
This solution outlines an approach to compute the maximum depth of a binary tree using C++ programming. The method used here is a depth-first search (DFS), leveraging an iterative strategy with a stack to avoid recursion.
This function maximumDepth
in the Solution
class determines the depth of the given binary tree by:
Checking if the input node (
TreeNode* node
) isNULL
. If true, it returns 0, indicating that the tree is empty, so there is no depth to measure.Initializing a vector of pairs,
stack
, which will store each node along with its corresponding depth level. The stack helps in iterating through the tree iteratively without using recursion.Starting with the root node, the code pushes the node and its depth level (starting at 1) onto the stack.
A while loop is utilized wherein each node is processed as long as the stack is not empty:
- The node at the top of the stack is evaluated.
- The current depth of this node is compared with the maximum depth found so far (
deepest
) and updated if necessary. - The node is then removed from the stack.
- The function then checks if the current node has left or right children. If so, these child nodes along with their depth level (current depth + 1) are pushed onto the stack.
After the while loop finishes (i.e., the stack is empty and all nodes have been evaluated), the function returns the value of
deepest
, which now contains the maximum depth of the binary tree.
This procedure efficiently handles the depth determination using a non-recursive method, ensuring that each node is visited only once and keeping track of the depth without additional memory overhead common in recursive solutions.
class Solution {
public int findMaxDepth(TreeNode node) {
LinkedList<TreeNode> nodes = new LinkedList<>();
LinkedList<Integer> depthCounts = new LinkedList<>();
if (node == null) return 0;
nodes.add(node);
depthCounts.add(1);
int maxDepth = 0, currentLevelDepth = 0;
while (!nodes.isEmpty()) {
node = nodes.pollLast();
currentLevelDepth = depthCounts.pollLast();
if (node != null) {
maxDepth = Math.max(maxDepth, currentLevelDepth);
nodes.add(node.left);
nodes.add(node.right);
depthCounts.add(currentLevelDepth + 1);
depthCounts.add(currentLevelDepth + 1);
}
}
return maxDepth;
}
}
The provided Java implementation demonstrates how to calculate the maximum depth (or height) of a binary tree using a breadth-first search approach. Here's a concise breakdown of how this solution operates:
A helper class,
TreeNode
, is expected to be defined elsewhere, which represents the tree nodes. EachTreeNode
should have aleft
andright
child.The main method in the
Solution
class,findMaxDepth
, takes the rootTreeNode
of the binary tree as a parameter.Two
LinkedList
instances are used:nodes
holds the tree nodes to be traversed.depthCounts
keeps track of the depth levels corresponding to each node in thenodes
list.
Initially, the root node is added to
nodes
if it is notnull
, and1
(indicating the starting depth level) is added todepthCounts
.The method then enters a loop that continues until there are no more nodes to process in the
nodes
list:- The last node and its depth count are removed from their respective lists.
- If the node being processed is not
null
, the method calculates the maximum depth encountered so far. - The node’s children (
left
andright
) are added to thenodes
list, and their corresponding depth counts (current node's depth + 1) are added to thedepthCounts
list.
The loop ensures that all nodes in the tree are visited, and for each node, the depth is correctly computed and potentially updated if it exceeds the previously recorded maximum depth.
After the loop concludes, the highest value recorded in
maxDepth
is returned as the maximum depth of the binary tree.
This implementation efficiently traverses the tree without recursively calling the function, thus potentially reducing stack space usage, which is particularly beneficial for trees with high depths.
struct Item {
struct TreeNode* itemNode;
int itemDepth;
};
struct Item* create_item(struct TreeNode* node, int depth) {
struct Item* newItem = malloc(sizeof(struct Item));
newItem->itemNode = node;
newItem->itemDepth = depth;
return newItem;
}
int calculateMaxDepth(struct TreeNode* root) {
if (root == NULL) {
return 0;
}
struct Item** nodeStack = malloc(10000 * sizeof(struct TreeNode*));
int stackPointer = 0;
nodeStack[stackPointer++] = create_item(root, 1);
int deepest = 0;
while (stackPointer != 0) {
struct Item* currentItem = nodeStack[--stackPointer];
int currentDepth = currentItem->itemDepth;
struct TreeNode* currentNode = currentItem->itemNode;
deepest = currentDepth > deepest ? currentDepth : deepest;
free(currentItem);
if (currentNode->left != NULL) {
nodeStack[stackPointer++] = create_item(currentNode->left, currentDepth + 1);
}
if (currentNode->right != NULL) {
nodeStack[stackPointer++] = create_item(currentNode->right, currentDepth + 1);
}
}
free(nodeStack);
return deepest;
}
This C language code determines the maximum depth of a binary tree using an iterative approach with a custom stack. It begins by defining a structure Item
, which encapsulates a tree node and its depth. Here's an overview of the process:
- A helper function
create_item
initializes and returns a newItem
containing a node and its depth. - The function
calculateMaxDepth
calculates the tree's maximum depth:- If the root is null, it returns 0, indicating an empty tree.
- Initializes a stack to store nodes as they are processed.
- Uses a loop to process each node in the stack. For the current node, if it is deeper than previously encountered nodes, it updates the
deepest
variable. - Nodes are explored depth-first, and their children are added to the stack with incremented depth.
Finally, the code handles memory correctly by dynamically allocating space for the stack and items, and freeing them once done processing. This efficient implementation ensures that the maximum depth of the tree is determined without using recursion, which can be advantageous for handling large trees or to avoid stack overflow in environments with limited stack size.
var calculateDepth = function (treeRoot) {
let nodeStack = [];
if (treeRoot != null) nodeStack.push({ node: treeRoot, current_depth: 1 });
let maxDepth = 0;
while (nodeStack.length > 0) {
let { node, current_depth } = nodeStack.pop();
if (node) {
maxDepth = Math.max(maxDepth, current_depth);
nodeStack.push({ node: node.left, current_depth: current_depth + 1 });
nodeStack.push({ node: node.right, current_depth: current_depth + 1 });
}
}
return maxDepth;
};
This article provides a solution for finding the maximum depth of a binary tree using JavaScript. The function calculateDepth
takes treeRoot
as its parameter, which represents the root of the binary tree.
- Start with an empty
nodeStack
array designed to keep track of nodes and their respective depths. - Push the root node into
nodeStack
if it's not null, with an initial depth of 1. - Initialize
maxDepth
to zero to hold the record of the deepest point reached in the tree. - Use a while loop to process each node in the stack until the stack is empty. During each iteration, pop the top node from the stack and:
- Update
maxDepth
usingMath.max
to compare the current maximum depth and the depth of the current node. - Push the left and right children of the current node onto the stack. Increase the depth by 1 for each child.
- Update
- Once the loop completes, return
maxDepth
as the solution.
By the end, the function returns the maximum depth of the binary tree, which is determined by the highest level reached by any node in the tree structure. This approach uses a stack to simulate recursive tree traversal, ensuring all nodes are examined.
class Solution:
def maxDepth(self, node: TreeNode) -> int:
nodes = []
if node:
nodes.append((1, node))
max_depth = 0
while nodes:
depth, node = nodes.pop()
if node:
max_depth = max(max_depth, depth)
nodes.append((depth + 1, node.left))
nodes.append((depth + 1, node.right))
return max_depth
The provided Python3 code defines a method maxDepth
for calculating the maximum depth of a binary tree. Here's the breakdown of the code's functionality:
- Define a class named
Solution
. - Inside
Solution
, define themaxDepth
method that accepts anode
parameter, which refers to the root node of a binary tree. - Initialize an empty list
nodes
to keep track of nodes to be explored along with their depth levels. - Check if the root node exists. If it does, add the root node and its depth level (1) to the
nodes
list. - Set
max_depth
to 0, which will store the maximum depth as the algorithm progresses. - Implement a while loop that runs as long as there are nodes left in the
nodes
list. This loop helps in exploring each node:- Pop the last entry from
nodes
to get the current node and its depth. - If the current node is not
None
, compare its depth withmax_depth
and updatemax_depth
if the current node's depth is greater. - Add child nodes (left and right) of the current node to the
nodes
list, with their depth incremented by 1.
- Pop the last entry from
- Once there are no nodes left to explore, return the value of
max_depth
, which is the maximum depth of the binary tree.
The method essentially performs a depth-first search of the binary tree using a stack (implemented with a list nodes
), tracking the maximum depth encountered throughout the traversal.
No comments yet.