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++ 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(); |
3
Time Complexity: O(N)
Auxiliary Space: O(N)