medium Maximum Binary Tree
Problem Statement
Given an integer array nums with no duplicates, construct a maximum binary tree from a given array by following these rules:
- The root of the tree is the highest value in the
nums. - The left subtree is recursively built from the elements to the left of the highest value in subarray prefix.
- The right subtree is recursively built from the elements to the right of the highest value in subarray suffix.
Return the resulting maximum binary tree.
Examples
Example 1:
- Input: nums =
[4, 3, 1, 7, 0, 5] - Expected Output:
[7, 4, 5, null, 3, 0, null, null, 1]
- Justification:
- The maximum value is 7, which becomes the root.
- Left subarray
[4, 3, 1]builds the left subtree:- Maximum is 4.
- Right subarray
[3, 1]builds further:- Maximum is 3 with right child 1.
- Right subarray
[0, 5]builds the right subtree:- Maximum is 5 with left child 0.
Example 2:
- Input: nums =
[1, 4, 3, 2] - Expected Output:
[4, 1, 3, null, null, null, 2]
- Justification:
- The maximum value is 4, which becomes the root.
- Left subarray
[1]becomes the left child. - Right subarray
[3, 2]builds the right subtree:- Maximum is 3 with right child 2.
Example 3:
- Input: nums =
[7, 2, 5, 3, 9, 1] - Expected Output:
[9, 7, 1, null, 5, null, null, 2, 3]
- Justification:
- The maximum value is 9, which becomes the root.
- Left subarray
[7, 2, 5, 3]builds the left subtree:- Maximum is 7.
- Right subarray
[2, 5, 3]builds further:- Maximum is 5 with left child 2 and right child 3.
- Right subarray
[1]becomes the right child.
Constraints:
- 1 <= nums.length <= 1000
- 0 <= nums[i] <= 1000
- All integers in nums are unique.
Try it yourself
Try solving this question here:
✅ Solution Maximum Binary Tree
Problem Statement
Given an integer array nums with no duplicates, construct a maximum binary tree from a given array by following these rules:
- The root of the tree is the highest value in the
nums. - The left subtree is recursively built from the elements to the left of the highest value in subarray prefix.
- The right subtree is recursively built from the elements to the right of the highest value in subarray suffix.
Return the resulting maximum binary tree.
Examples
Example 1:
- Input: nums =
[4, 3, 1, 7, 0, 5] - Expected Output:
[7, 4, 5, null, 3, 0, null, null, 1]
- Justification:
- The maximum value is 7, which becomes the root.
- Left subarray
[4, 3, 1]builds the left subtree:- Maximum is 4.
- Right subarray
[3, 1]builds further:- Maximum is 3 with right child 1.
- Right subarray
[0, 5]builds the right subtree:- Maximum is 5 with left child 0.
Example 2:
- Input: nums =
[1, 4, 3, 2] - Expected Output:
[4, 1, 3, null, null, null, 2]
- Justification:
- The maximum value is 4, which becomes the root.
- Left subarray
[1]becomes the left child. - Right subarray
[3, 2]builds the right subtree:- Maximum is 3 with right child 2.
Example 3:
- Input: nums =
[7, 2, 5, 3, 9, 1] - Expected Output:
[9, 7, 1, null, 5, null, null, 2, 3]
- Justification:
- The maximum value is 9, which becomes the root.
- Left subarray
[7, 2, 5, 3]builds the left subtree:- Maximum is 7.
- Right subarray
[2, 5, 3]builds further:- Maximum is 5 with left child 2 and right child 3.
- Right subarray
[1]becomes the right child.
Constraints:
- 1 <= nums.length <= 1000
- 0 <= nums[i] <= 1000
- All integers in nums are unique.
Solution
To construct the Maximum Binary Tree from the given array of unique integers, we employ a Divide and Conquer strategy. This approach systematically breaks down the problem into smaller, more manageable subproblems, ensuring that each segment of the array is processed efficiently.
Divide:
- Identify the Maximum: For any given subarray, we first locate the maximum value. This value becomes the root of the current subtree.
- Divide the Array: Once the maximum is identified, the array is divided into two parts:
- Left Subarray: Elements to the left of the maximum value.
- Right Subarray: Elements to the right of the maximum value.
Conquer:
- Recursive Construction: We recursively apply the same process to the left and right subarrays to construct the left and right subtrees, respectively.
- Base Case: If a subarray is empty (i.e., the start index equals the end index), we return
null, indicating no further nodes to add.
This divide and conquer approach is effective because it ensures that each subtree is constructed optimally by always selecting the maximum available value as the root, thereby maintaining the properties of the Maximum Binary Tree. Additionally, by recursively handling smaller subarrays, the algorithm efficiently builds the entire tree with clear parent-child relationships.
Step-by-Step Algorithm
-
Recursive Tree Construction:
- Check for Base Case:
- If
startis equal toend, returnnullto handle an empty array.
- If
- Identify the Maximum Element:
- Call
findIndexOfMaximum(nums, start, end)to find the index of the largest number in the current subarray.- The maximum value becomes the root of the current subtree, ensuring the tree adheres to the Maximum Binary Tree properties.
- Call
- Create the Root Node:
- Instantiate a new
TreeNodewith the valuenums[maxIndex].- This steps establishes the root of the subtree based on the identified maximum value.
- Instantiate a new
- Construct the Left Subtree:
- Recursively call
buildTree(nums, start, maxIndex)and assign the result toroot.left.- This step builds the left subtree using elements to the left of the maximum value, maintaining the tree structure.
- Recursively call
- Construct the Right Subtree:
- Recursively call
buildTree(nums, maxIndex + 1, end)and assign the result toroot.right.- This step builds the right subtree using elements to the right of the maximum value, ensuring all elements are included in the tree.
- Recursively call
- Return the Root Node:
- After assigning both left and right children, return the
rootnode.
- After assigning both left and right children, return the
- Check for Base Case:
-
Find the Index of the Maximum Value:
- In the
findIndexOfMaximummethod:- Initialize
maxIndextostart.- Here, we assume that the first element of the subarray is the maximum initially.
- Iterate from
starttoend - 1:- For each index
i, ifnums[i] > nums[maxIndex], updatemaxIndextoi.- This step identifies the true maximum value in the subarray by comparison.
- For each index
- Return
maxIndex.- This step provides the position of the maximum value to determine the root of the subtree.
- Initialize
- In the
Algorithm Walkthrough
Let's demonstrate the algorithm using Example 1:
Example 1:
- Input:
nums = [4, 3, 1, 7, 0, 5] - Expected Output:
[7, 4, 5, null, 3, 0, null, null, 1]
-
Start with the Entire Array:
- Call
buildMaximumBinaryTree(nums), which invokesbuildTree(nums, 0, 6)for the full array[4, 3, 1, 7, 0, 5].
- Call
-
First Recursive Call (Root Node):
- Subarray:
[4, 3, 1, 7, 0, 5] - Maximum Value:
7at index3. CreateTreeNode(7). - Recursive Calls:
- Left Subtree: Call
buildTree(nums, 0, 3)for[4, 3, 1]. - Right Subtree: Call
buildTree(nums, 4, 6)for[0, 5].
- Left Subtree: Call
- Subarray:
-
Second Recursive Call (Left Subtree of 7):
- Subarray:
[4, 3, 1] - Maximum Value:
4at index0. CreateTreeNode(4). - Recursive Calls:
- Left Subtree: Call
buildTree(nums, 0, 0)for an empty subarray (returnsnull). - Right Subtree: Call
buildTree(nums, 1, 3)for[3, 1].
- Left Subtree: Call
- Subarray:
-
Third Recursive Call (Right Subtree of 4):
- Subarray:
[3, 1] - Maximum Value:
3at index1. CreateTreeNode(3). - Recursive Calls:
- Left Subtree: Call
buildTree(nums, 1, 1)for an empty subarray (returnsnull). - Right Subtree: Call
buildTree(nums, 2, 3)for[1].
- Left Subtree: Call
- Subarray:
-
Fourth Recursive Call (Right Subtree of 3):
- Subarray:
[1] - Maximum Value:
1at index2. CreateTreeNode(1). - Recursive Calls:
- Left Subtree: Call
buildTree(nums, 2, 2)for an empty subarray (returnsnull). - Right Subtree: Call
buildTree(nums, 3, 3)for an empty subarray (returnsnull).
- Left Subtree: Call
- Subarray:
-
Second Recursive Call Returns:
TreeNode(4)is completed with:- Left child:
null - Right child:
TreeNode(3)→TreeNode(3).right = TreeNode(1)
- Left child:
-
First Recursive Call Proceeds to Right Subtree of 7:
- Subarray:
[0, 5] - Maximum Value:
5at index5. CreateTreeNode(5). - Recursive Calls:
- Left Subtree: Call
buildTree(nums, 4, 5)for[0]. - Right Subtree: Call
buildTree(nums, 6, 6)for an empty subarray (returnsnull).
- Left Subtree: Call
- Subarray:
-
Third Recursive Call (Left Subtree of 5):
- Subarray:
[0] - Maximum Value:
0at index4. CreateTreeNode(0). - Recursive Calls:
- Left Subtree: Call
buildTree(nums, 4, 4)for an empty subarray (returnsnull). - Right Subtree: Call
buildTree(nums, 5, 5)for an empty subarray (returnsnull).
- Left Subtree: Call
- Subarray:
-
First Recursive Call Completes:
TreeNode(7)is completed with:- Left child:
TreeNode(4)→TreeNode(4).right = TreeNode(3) → TreeNode(3).right = TreeNode(1) - Right child:
TreeNode(5)→TreeNode(5).left = TreeNode(0)
- Left child:
Code
import java.util.*;
// class TreeNode {
// int val;
// TreeNode left;
// TreeNode right;
// TreeNode(int x) { val = x; }
// }
public class Solution {
public TreeNode buildMaximumBinaryTree(int[] nums) {
return buildTree(nums, 0, nums.length);
}
private TreeNode buildTree(int[] nums, int start, int end) {
// Base case: if the current subarray is empty, return null
if (start == end) {
return null;
}
// Find the index of the maximum value in the current subarray
int maxIndex = findIndexOfMaximum(nums, start, end);
// Create a new TreeNode with the maximum value
TreeNode root = new TreeNode(nums[maxIndex]);
// Recursively build the left subtree from the left subarray
root.left = buildTree(nums, start, maxIndex);
// Recursively build the right subtree from the right subarray
root.right = buildTree(nums, maxIndex + 1, end);
return root;
}
private int findIndexOfMaximum(int[] nums, int start, int end) {
int maxIndex = start;
// Iterate through the subarray to find the maximum value's index
for (int i = start; i < end; i++) {
if (nums[i] > nums[maxIndex]) {
maxIndex = i;
}
}
return maxIndex;
}
private static List<Integer> serializeTree(TreeNode root) {
List<Integer> serialized = new ArrayList<>();
if (root == null) {
return serialized;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode current = queue.poll();
if (current != null) {
serialized.add(current.val);
queue.offer(current.left);
queue.offer(current.right);
} else {
serialized.add(null);
}
}
// Remove trailing nulls for a cleaner representation
int i = serialized.size() - 1;
while (i >= 0 && serialized.get(i) == null) {
serialized.remove(i);
i--;
}
return serialized;
}
public static void main(String[] args) {
Solution solution = new Solution();
// Example 1
int[] nums1 = { 4, 3, 1, 7, 0, 5 };
TreeNode tree1 = solution.buildMaximumBinaryTree(nums1);
List<Integer> output1 = serializeTree(tree1);
System.out.println("Example 1 Output: " + output1);
// Expected Output: [7, 4, 5, null, 3, 0, null, null, 1]
// Example 2
int[] nums2 = { 1, 4, 3, 2 };
TreeNode tree2 = solution.buildMaximumBinaryTree(nums2);
List<Integer> output2 = serializeTree(tree2);
System.out.println("Example 2 Output: " + output2);
// Expected Output: [4, 1, 3, null, null, null, 2]
// Example 3
int[] nums3 = { 7, 2, 5, 3, 9, 1 };
TreeNode tree3 = solution.buildMaximumBinaryTree(nums3);
List<Integer> output3 = serializeTree(tree3);
System.out.println("Example 3 Output: " + output3);
// Expected Output: [9, 7, 1, null, 5, null, null, 2, 3]
}
}
Complexity Analysis
Time Complexity:
-
Finding the Maximum Index:
- The
findIndexOfMaximummethod scans the subarray fromstarttoend - 1to locate the maximum value. In the worst-case scenario (e.g., when the array is sorted in decreasing order), this scan takestime for each recursive call.
- The
-
Recursive Tree Construction:
- The
buildTreemethod is called recursively for the left and right subarrays. In the worst case, where each recursive call only reduces the problem size by one (e.g., sorted in decreasing order), the depth of recursion becomes n. - At each level of recursion, finding the maximum takes
time, leading to a total time complexity of .
- The
-
Overall Time Complexity:
- The dominant factor is the recursive tree construction with
time complexity. Thus, the overall time complexity of the algorithm is .
- The dominant factor is the recursive tree construction with
Space Complexity:
- Recursive Call Stack:
- The depth of the recursion tree depends on the structure of the input array. In the worst case (e.g., sorted in decreasing order), the recursion depth becomes n, leading to
space consumed by the call stack.
- The depth of the recursion tree depends on the structure of the input array. In the worst case (e.g., sorted in decreasing order), the recursion depth becomes n, leading to
- Tree Storage:
-
The constructed binary tree consists of n nodes, each occupying constant space. Therefore, storing the tree requires
space.
-
- Overall Space Complexity:
- The dominant factors are the recursion stack and the storage for the tree and serialization, each requiring
space. Thus, the overall space complexity of the algorithm is .
- The dominant factors are the recursion stack and the storage for the tree and serialization, each requiring
🤖 Don't fully get this? Learn it with Claude
Stuck on Maximum Binary Tree? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Progressively stronger hints — you still solve it.
I'm working on the problem **Maximum Binary Tree** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
See the technique, not just code.
Explain the optimal approach to **Maximum Binary Tree** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Catch bugs, edge cases, sub-optimality.
I'll paste my solution to **Maximum Binary Tree**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Lock in recognition with look-alikes.
Give me 2 problems that use the SAME underlying pattern as **Maximum Binary Tree**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.