Skip to main content

Command Palette

Search for a command to run...

Solving Leetcode Interviews in Seconds with AI: Merge BSTs to Create Single BST

Updated
4 min read

Introduction

In this blog post, we will explore how to solve the LeetCode problem "1932" using AI. LeetCode is a popular platform for preparing for coding interviews, and with the help of AI tools like Chatmagic, we can generate solutions quickly and efficiently - helping you pass the interviews and get the job offer without having to study for months.

Problem Statement

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: Select two distinct indices 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]. Replace the leaf node in trees[i] with trees[j]. Remove 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: Every node in the node's left subtree has a value strictly less than the node's value. Every node in the node's right subtree has a value strictly greater than the node's value. 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 The number of nodes in each tree is in the range [1, 3]. Each node in the input may have children but no grandchildren. No two roots of trees have the same value. All the trees in the input are valid BSTs. 1 <= TreeNode.val <= 5 104.

Explanation

Here's a breakdown of the solution approach and the Python code:

  • Core Idea: The problem boils down to finding a way to merge the given BSTs into a single valid BST. We can achieve this by iteratively finding a leaf node in one tree that matches the root of another, and merging. Key is to build a graph representing potential merges. Detect and handle cycles as the merging process may create cycles. The root of the final BST is the node with no incoming edges. After merging, validate that resulting tree is a valid BST.
  • Steps:

    1. Build a Merge Graph: Create a graph where nodes are root values, and edges represent potential merges (leaf value in tree i matches root value of tree j). Also, create a map of root value to the actual tree node.
    2. Find the Root: Determine the root of the final BST. This is the node (root value) with no incoming edges in the merge graph. If there isn't exactly one root, merging isn't possible.
    3. Merge Trees: Starting from the root, perform a depth-first search (DFS) to merge the trees. If the leaf is smaller than the root replace the left child, otherwise the right child. Use the graph to determine which trees to merge into the current tree's leaves.
    4. Validate BST: Finally, validate that the merged tree is indeed a valid BST.
  • Complexity:

    • Runtime Complexity: O(N), where N is the number of trees.
    • Storage Complexity: O(N).

Code

    from typing import List, Optional

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def can_merge(trees: List[Optional[TreeNode]]) -> Optional[TreeNode]:
    """
    Merges the given BSTs into a single valid BST if possible.

    Args:
        trees: A list of BST root nodes.

    Returns:
        The root of the resulting BST if it is possible to form a valid BST,
        or None otherwise.
    """

    if not trees:
        return None

    val_to_node = {tree.val: tree for tree in trees}
    graph = {}
    in_degree = {}

    for tree in trees:
        graph[tree.val] = []
        in_degree[tree.val] = 0

    for tree in trees:
        if tree.left:
            if tree.left.val in val_to_node:
                graph[tree.val].append(tree.left.val)
                in_degree[tree.left.val] = in_degree.get(tree.left.val, 0) + 1
        if tree.right:
            if tree.right.val in val_to_node:
                graph[tree.val].append(tree.right.val)
                in_degree[tree.right.val] = in_degree.get(tree.right.val, 0) + 1

    roots = [node for node in in_degree if in_degree[node] == 0]
    if len(roots) != 1:
        return None

    root_val = roots[0]
    root = val_to_node[root_val]
    val_to_node.pop(root_val)

    def merge(node: TreeNode):
        if node.left and node.left.val in val_to_node:
            child = val_to_node.pop(node.left.val)
            node.left = child
            merge(child)

        if node.right and node.right.val in val_to_node:
            child = val_to_node.pop(node.right.val)
            node.right = child
            merge(child)

    merge(root)

    if val_to_node:
        return None

    def is_valid_bst(node: Optional[TreeNode], min_val=float('-inf'), max_val=float('inf')) -> bool:
        if not node:
            return True

        if not (min_val < node.val < max_val):
            return False

        return is_valid_bst(node.left, min_val, node.val) and is_valid_bst(node.right, node.val, max_val)

    if not is_valid_bst(root):
        return None

    return root

More from this blog

C

Chatmagic blog

2894 posts