You are given n
BST (binary search tree) root nodes for n
separate BSTs stored in an array trees
(0-indexed). Each BST in trees
has at most 3 nodes, and no two roots have the same value. In one operation, you can:
i
and j
such that the value stored at one of the leaves of trees[i]
is equal to the root value of trees[j]
.trees[i]
with trees[j]
.trees[j]
from trees
.Return the root of the resulting BST if it is possible to form a valid BST after performing n - 1
operations, or null
if it is impossible to create a valid BST.
A BST (binary search tree) is a binary tree where each node satisfies the following property:
A leaf is a node that has no children.
Example 1:
Input: trees = [[2,1],[3,2,5],[5,4]] Output: [3,2,5,1,null,4] Explanation: In the first operation, pick i=1 and j=0, and merge trees[0] into trees[1]. Delete trees[0], so trees = [[3,2,5,1],[5,4]].In the second operation, pick i=0 and j=1, and merge trees[1] into trees[0]. Delete trees[1], so trees = [[3,2,5,1,null,4]].
The resulting tree, shown above, is a valid BST, so return its root.
Example 2:
Input: trees = [[5,3,8],[3,2,6]] Output: [] Explanation: Pick i=0 and j=1 and merge trees[1] into trees[0]. Delete trees[1], so trees = [[5,3,8,2,6]].The resulting tree is shown above. This is the only valid operation that can be performed, but the resulting tree is not a valid BST, so return null.
Example 3:
Input: trees = [[5,4],[3]] Output: [] Explanation: It is impossible to perform any operations.
Constraints:
n == trees.length
1 <= n <= 5 * 104
[1, 3]
.trees
have the same value.1 <= TreeNode.val <= 5 * 104
.This problem requires merging multiple Binary Search Trees (BSTs) with at most three nodes each into a single valid BST. The core challenge lies in determining the feasibility of merging and ensuring the resulting tree adheres to BST properties.
Approach:
The solution employs a recursive depth-first search (DFS) approach combined with backtracking to explore all possible merging sequences.
Base Case: If only one BST remains, it's the final result.
Recursive Step: For each pair of BSTs, we check if a merge is possible. A merge is possible if a leaf node in one BST matches the root of another.
Merge Operation: If a merge is possible, we perform it:
Backtracking: If a merge doesn't lead to a valid final BST, we backtrack (undo the merge) and explore other possibilities.
Validation: After each potential merge, we validate if the resulting tree is a valid BST using a helper function. A valid BST ensures that all nodes in the left subtree are smaller and all nodes in the right subtree are larger than the current node.
Code (Python):
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def is_valid_bst(root):
def helper(node, min_val, max_val):
if not node:
return True
if not (min_val < node.val < max_val):
return False
return helper(node.left, min_val, node.val) and helper(node.right, node.val, max_val)
return helper(root, float('-inf'), float('inf'))
def merge_bsts(trees):
def solve(trees):
if len(trees) == 1:
return trees[0]
for i in range(len(trees)):
for j in range(len(trees)):
if i == j:
continue
tree1 = trees[i]
tree2 = trees[j]
#Attempt merges
if merge_possible(tree1,tree2):
new_tree = merge_trees(tree1,tree2)
new_trees = [t for k,t in enumerate(trees) if k !=j]
new_trees[i] = new_tree
result = solve(new_trees)
if result:
return result
return None
def merge_possible(tree1, tree2):
#Check leaves of tree1 against root of tree2
q = [tree1]
while q:
curr = q.pop(0)
if not curr.left and not curr.right and curr.val == tree2.val:
return True
if curr.left:
q.append(curr.left)
if curr.right:
q.append(curr.right)
return False
def merge_trees(tree1,tree2):
q = [tree1]
while q:
curr = q.pop(0)
if not curr.left and not curr.right and curr.val == tree2.val:
curr.left = tree2
return tree1
if curr.left:
q.append(curr.left)
if curr.right:
q.append(curr.right)
return None
result = solve(trees)
return result if is_valid_bst(result) else None
Time Complexity: O(N * 3^N), where N is the number of trees. In the worst case, we may explore all possible merging sequences. Each merge operation takes constant time. The is_valid_bst
function takes linear time in the size of the tree, and the tree's size grows with each merge.
Space Complexity: O(N) in the worst case due to the recursion depth and the space needed to store the trees.
Other Languages: The core logic remains similar in Java, C++, or Go. You would need to adapt the TreeNode class and potentially the implementation details for merging and validation based on the specific language features. The time and space complexities would remain the same.