Open In App

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

Last Updated : 09 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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:

  • Create a Hashtable to store the subtree, sum of node values in a subtree, minimum value in the subtree, and maximum value in a subtree.
  • Initialize the ans as infinity or the maximum possible value.
  • Now recursively check for the given tree and its subtrees if it is BST or not.
  • In each recursive call, save the value of the sum of nodes for each subtree, the subtree node count(subtree length) for every subtree, the minimum value of the subtree, the maximum value of the subtree.
  • If the given subtree is a BST and the sum of nodes of the subtree is equal to the given target update the ans as the minimum of the number of nodes in this subtree or subtree length and previous answer value.
  • return true if the given subtree is a BST else return false.
  • In the end, the answer will contain the minimum number of nodes in a subtree for a given target or it will be infinity if no answer exists for a given binary tree.

Below is the implementation of the above approach:

C++




// 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




// 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


Python3




# 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#




// 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


Javascript




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)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads