LeetCode in Kotlin

1932. Merge BSTs to Create Single BST

Hard

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:

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:

Solution

import com_github_leetcode.TreeNode

/*
 * Example:
 * var ti = TreeNode(5)
 * var v = ti.`val`
 * Definition for a binary tree node.
 * class TreeNode(var `val`: Int) {
 *     var left: TreeNode? = null
 *     var right: TreeNode? = null
 * }
 */
class Solution {
    fun canMerge(trees: List<TreeNode>): TreeNode? {
        val valToNode: MutableMap<Int, TreeNode> = HashMap()
        val count: MutableMap<Int, Int> = HashMap()
        for (tree in trees) {
            valToNode[tree.`val`] = tree
            count.merge(
                tree.`val`, 1
            ) { a: Int?, b: Int? ->
                Integer.sum(
                    a!!, b!!
                )
            }
            if (tree.left != null) count.merge(
                tree.left!!.`val`, 1
            ) { a: Int?, b: Int? ->
                Integer.sum(
                    a!!, b!!
                )
            }
            if (tree.right != null) count.merge(
                tree.right!!.`val`, 1
            ) { a: Int?, b: Int? ->
                Integer.sum(
                    a!!, b!!
                )
            }
        }
        for (tree in trees) if (count[tree.`val`] == 1) {
            return if (isValidBST(tree, null, null, valToNode) &&
                valToNode.size <= 1
            ) tree else null
        }
        return null
    }

    fun isValidBST(
        tree: TreeNode?,
        minNode: TreeNode?,
        maxNode: TreeNode?,
        valToNode: MutableMap<Int, TreeNode>
    ): Boolean {
        if (tree == null) return true
        if (minNode != null && tree.`val` <= minNode.`val`) return false
        if (maxNode != null && tree.`val` >= maxNode.`val`) return false
        if (tree.left == null && tree.right == null && valToNode.containsKey(tree.`val`)) {
            val `val` = tree.`val`
            tree.left = valToNode[`val`]!!.left
            tree.right = valToNode[`val`]!!.right
            valToNode.remove(`val`)
        }
        return isValidBST(tree.left, minNode, tree, valToNode) &&
            isValidBST(tree.right, tree, maxNode, valToNode)
    }
}