0% completed
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
start
is equal toend
, returnnull
to 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
TreeNode
with 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
root
node.
- After assigning both left and right children, return the
- Check for Base Case:
-
Find the Index of the Maximum Value:
- In the
findIndexOfMaximum
method:- Initialize
maxIndex
tostart
.- Here, we assume that the first element of the subarray is the maximum initially.
- Iterate from
start
toend - 1
:- For each index
i
, ifnums[i] > nums[maxIndex]
, updatemaxIndex
toi
.- 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:
7
at 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:
4
at 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:
3
at 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:
1
at 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:
5
at 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:
0
at 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
Complexity Analysis
Time Complexity: O(n^2)
-
Finding the Maximum Index:
- The
findIndexOfMaximum
method scans the subarray fromstart
toend - 1
to locate the maximum value. In the worst-case scenario (e.g., when the array is sorted in decreasing order), this scan takes O(n) time for each recursive call.
- The
-
Recursive Tree Construction:
- The
buildTree
method 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 O(n) time, leading to a total time complexity of O(n^2).
- The
-
Overall Time Complexity:
- The dominant factor is the recursive tree construction with O(n^2) time complexity. Thus, the overall time complexity of the algorithm is O(n^2).
Space Complexity: O(n)
- 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 O(n) space consumed by the call stack.
- Tree Storage:
-
The constructed binary tree consists of n nodes, each occupying constant space. Therefore, storing the tree requires O(n) space.
-
- Overall Space Complexity:
- The dominant factors are the recursion stack and the storage for the tree and serialization, each requiring O(n) space. Thus, the overall space complexity of the algorithm is O(n).
.....
.....
.....
Table of Contents
Contents are not accessible
Contents are not accessible
Contents are not accessible
Contents are not accessible
Contents are not accessible