Open In App

Find the minimum Sub-tree with target sum in a Binary search tree

Given a binary tree and a target, find the number of nodes in the minimum sub-tree with the given sum equal to the target which is also a binary search tree.

Examples:



Input:
          13
        /    \
      5       23
     / \       / \
  N  17 N   N
       /
     16
Target: 38
Output: 3
Explanation: 5, 17, 16 is the smallest subtree with length 3.

Input:
            7
          /   \
       N    23
            /   \
        10    23
        /  \   / \
    N  17 N  N
Target: 73
Output: -1
Explanation: No subtree is bst for the given target.



Approach: The problem can be solved using the below idea:

This problem can be solved using Dynamic Programming on Trees.

Below are the steps for the above approach:

Below is the implementation of the above approach:




// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
 
class Node {
public:
    int data;
    Node *left, *right;
    Node(int x)
    {
        this->data = x;
        this->left = 0;
        this->right = 0;
    }
};
 
class Solution {
    unordered_map<Node *, int> subTreeLength, sum, mnE, mxE;
    int minLength = INT_MAX;
    int target;
 
public:
    int minSubtreeSumBST(int target, Node* root)
    {
        this->target = target;
        isBST(root);
        return minLength == INT_MAX ? -1 : minLength;
    }
    int isBST(Node* root)
    {
        if (root == 0)
            return 1;
        int l = isBST(root->left);
        int r = isBST(root->right);
        sum[root] = root->data + sum[root->left]
                    + sum[root->right];
        mnE[root]
            = root->left ? mnE[root->left] : root->data;
        mxE[root]
            = root->right ? mxE[root->right] : root->data;
        subTreeLength[root] = 1 + subTreeLength[root->left]
                              + subTreeLength[root->right];
        if ((root->left ? mxE[root->left] < root->data : 1)
            and (root->right ? mnE[root->right] > root->data
                             : 1)
            and l and r) {
            if (target == sum[root])
                minLength
                    = min(minLength, subTreeLength[root]);
            return 1;
        }
        return 0;
    }
};
 
// Drivers code
int main()
{
 
    int target = 38;
    Node* root = new Node(13);
    root->left = new Node(5);
    root->right = new Node(23);
    root->left->right = new Node(17);
    root->left->right->left = new Node(16);
    Solution obj;
 
    // Function Call
    cout << obj.minSubtreeSumBST(target, root);
    return 0;
}




// JAVA code for the above approach:
import java.util.HashMap;
 
class Node {
    int data;
    Node left, right;
 
    Node(int x) {
        this.data = x;
        this.left = null;
        this.right = null;
    }
}
 
class Solution {
    // HashMaps to store information for each node
    HashMap<Node, Integer> subTreeLength, sum, mnE, mxE;
    int minLength = Integer.MAX_VALUE;
    int target;
 
    int minSubtreeSumBST(int target, Node root) {
        this.target = target;
        subTreeLength = new HashMap<>();
        sum = new HashMap<>();
        mnE = new HashMap<>();
        mxE = new HashMap<>();
        isBST(root);
        return minLength == Integer.MAX_VALUE ? -1 : minLength;
    }
 
    int isBST(Node root) {
        // Base case: empty node
        if (root == null)
            return 1;
 
        // Recursively check if left and right subtrees are BSTs
        int l = isBST(root.left);
        int r = isBST(root.right);
 
        // Calculate sum, minimum, and maximum values for the current node
        sum.put(root, root.data + sum.getOrDefault(root.left, 0) + sum.getOrDefault(root.right, 0));
        mnE.put(root, root.left != null ? mnE.get(root.left) : root.data);
        mxE.put(root, root.right != null ? mxE.get(root.right) : root.data);
        subTreeLength.put(root, 1 + subTreeLength.getOrDefault(root.left, 0) + subTreeLength.getOrDefault(root.right, 0));
 
        // Check if the current node forms a valid BST subtree with the given properties
        if ((root.left != null ? mxE.get(root.left) < root.data : true)
                && (root.right != null ? mnE.get(root.right) > root.data : true)
                && l != 0 && r != 0) {
            // If the subtree sum matches the target, update the minimum length if necessary
            if (target == sum.get(root))
                minLength = Math.min(minLength, subTreeLength.get(root));
            return 1;
        }
 
        return 0;
    }
}
 
public class Main {
 
    public static void main(String[] args) {
 
        // Test case
        int target = 38;
        Node root = new Node(13);
        root.left = new Node(5);
        root.right = new Node(23);
        root.left.right = new Node(17);
        root.left.right.left = new Node(16);
        Solution obj = new Solution();
 
        // Function call to find the minimum subtree sum BST length
        int result = obj.minSubtreeSumBST(target, root);
        System.out.println("Minimum subtree sum BST length: " + result);
    }
}
 
// This code is contributed by shivamgupta310570




# Python code for the above approach
class Node:
    def __init__(self, x):
        self.data = x
        self.left = None
        self.right = None
 
class Solution:
    def __init__(self):
        self.subTreeLength = {}  # Stores the length of subtrees
        self.sum = {}  # Stores the sum of values in subtrees
        self.mnE = {}  # Stores the minimum value in the right subtree
        self.mxE = {}  # Stores the maximum value in the left subtree
        self.minLength = float('inf'# Minimum subtree length with the target sum
        self.target = 0  # The target sum to find
 
    def minSubtreeSumBST(self, target, root):
        self.target = target
        self.subTreeLength = {}
        self.sum = {}
        self.mnE = {}
        self.mxE = {}
        self.isBST(root)
        return self.minLength if self.minLength != float('inf') else -1
 
    def isBST(self, root):
        # Base case: empty node
        if root is None:
            return 1
 
        # Recursively check if left and right subtrees are BSTs
        l = self.isBST(root.left)
        r = self.isBST(root.right)
 
        # Calculate sum, minimum, and maximum values for the current node
        self.sum[root] = root.data + (self.sum.get(root.left, 0) if root.left else 0) + (self.sum.get(root.right, 0) if root.right else 0)
        self.mnE[root] = self.mnE.get(root.left, root.data) if root.left else root.data
        self.mxE[root] = self.mxE.get(root.right, root.data) if root.right else root.data
        self.subTreeLength[root] = 1 + (self.subTreeLength.get(root.left, 0) if root.left else 0) + (self.subTreeLength.get(root.right, 0) if root.right else 0)
 
        # Check if the current node forms a valid BST subtree with the given properties
        if (not root.left or self.mxE[root.left] < root.data) and (not root.right or self.mnE[root.right] > root.data) and l and r:
            # If the subtree sum matches the target, update the minimum length if necessary
            if self.target == self.sum[root]:
                self.minLength = min(self.minLength, self.subTreeLength[root])
            return 1
 
        return 0
 
# Driver code
if __name__ == "__main__":
    target = 38
    root = Node(13)
    root.left = Node(5)
    root.right = Node(23)
    root.left.right = Node(17)
    root.left.right.left = Node(16)
    obj = Solution()
 
    # Function call to find the minimum subtree sum BST length
    print(obj.minSubtreeSumBST(target, root))
 
# This code is contributed by Susobhan Akhuli




// C# code for the above approach
using System;
using System.Collections.Generic;
 
public class Node {
    public int data;
    public Node left, right;
 
    public Node(int x)
    {
        this.data = x;
        this.left = null;
        this.right = null;
    }
}
 
public class Solution {
    // Dictionaries to store information for each node
    Dictionary<Node, int> subTreeLength, sum, mnE, mxE;
    int minLength = int.MaxValue;
    int target;
 
    public int MinSubtreeSumBST(int target, Node root)
    {
        this.target = target;
        subTreeLength = new Dictionary<Node, int>();
        sum = new Dictionary<Node, int>();
        mnE = new Dictionary<Node, int>();
        mxE = new Dictionary<Node, int>();
        IsBST(root);
        return minLength == int.MaxValue ? -1 : minLength;
    }
 
    public int IsBST(Node root)
    {
        // Base case: empty node
        if (root == null)
            return 1;
 
        // Recursively check if left and right subtrees are
        // BSTs
        int l = IsBST(root.left);
        int r = IsBST(root.right);
 
        // Calculate sum, minimum, and maximum values for
        // the current node
        int leftSum = 0;
        int rightSum = 0;
        if (root.left != null) {
            leftSum = sum[root.left];
        }
        if (root.right != null) {
            rightSum = sum[root.right];
        }
        sum[root] = root.data + leftSum + rightSum;
 
        int leftMin = root.left != null ? mnE[root.left]
                                        : root.data;
        int rightMax = root.right != null ? mxE[root.right]
                                          : root.data;
        mnE[root] = Math.Min(root.data, leftMin);
        mxE[root] = Math.Max(root.data, rightMax);
 
        subTreeLength[root]
            = 1
              + (root.left != null
                     ? subTreeLength[root.left]
                     : 0)
              + (root.right != null
                     ? subTreeLength[root.right]
                     : 0);
 
        // Check if the current node forms a valid BST
        // subtree with the given properties
        if ((root.left != null ? mxE[root.left] < root.data
                               : true)
            && (root.right != null
                    ? mnE[root.right] > root.data
                    : true)
            && l != 0 && r != 0) {
            // If the subtree sum matches the target, update
            // the minimum length if necessary
            if (target == sum[root])
                minLength = Math.Min(minLength,
                                     subTreeLength[root]);
            return 1;
        }
 
        return 0;
    }
}
 
public class GFG {
    public static void Main(string[] args)
    {
        // Test case
        int target = 38;
        Node root = new Node(13);
        root.left = new Node(5);
        root.right = new Node(23);
        root.left.right = new Node(17);
        root.left.right.left = new Node(16);
        Solution obj = new Solution();
 
        // Function call to find the minimum subtree sum BST
        // length
        int result = obj.MinSubtreeSumBST(target, root);
        Console.WriteLine(result);
    }
}
 
// This code is contributed by Susobhan Akhuli




class Node {
  constructor(x) {
    this.data = x;
    this.left = null;
    this.right = null;
  }
}
// Define a class for the solution to
// find the minimum subtree sum BST
class GFG {
  constructor() {
    // Maps to store various properties of each node
    this.subTreeLength = new Map();
    this.sum = new Map();
    this.mnE = new Map();
    this.mxE = new Map();
    this.minLength = Infinity;
    this.target = 0;
  }
  // Method to find the minimum subtree sum BST
  minSubtreeSumBST(target, root) {
    this.target = target;
    this.isBST(root);
    return this.minLength === Infinity ? -1 : this.minLength;
  }
  // Helper method to traverse the tree and
  // find the minimum subtree sum BST
  isBST(root) {
    if (!root) {
      return 1;
    }
    const l = this.isBST(root.left);
    const r = this.isBST(root.right);
    // Calculate properties of the current node
    this.sum.set(root, root.data + (this.sum.get(root.left) || 0) + (this.sum.get(root.right) || 0));
    this.mnE.set(root, root.left ? this.mnE.get(root.left) : root.data);
    this.mxE.set(root, root.right ? this.mxE.get(root.right) : root.data);
    this.subTreeLength.set(root, 1 + (this.subTreeLength.get(root.left) || 0) + (this.subTreeLength.get(root.right) || 0));
    // Check if the current node's subtree forms a valid BST
    if (
      (!root.left || this.mxE.get(root.left) < root.data) &&
      (!root.right || this.mnE.get(root.right) > root.data) &&
      l && r
    ) {
      if (this.target === this.sum.get(root)) {
        this.minLength = Math.min(this.minLength, this.subTreeLength.get(root));
      }
      return 1;
    }
    return 0;
  }
}
// Driver code
function main() {
  const target = 38;
  const root = new Node(13);
  root.left = new Node(5);
  root.right = new Node(23);
  root.left.right = new Node(17);
  root.left.right.left = new Node(16);
  const obj = new GFG();
  // Call the method to find the minimum subtree sum BST and
  // log the result
  console.log(obj.minSubtreeSumBST(target, root));
}
main();

Output
3






Time Complexity: O(N)
Auxiliary Space: O(N)


Article Tags :