Find the minimum Subtree with target sum in a Binary search tree
Last Updated : 15 Sep, 2026
Given the root of a binary tree and an integer target, find the size (number of nodes) of the smallest subtree whose sum of node values is equal to target and that is also a Binary Search Tree (BST). If no such subtree exists, return -1.
Examples:
Input: root = [13, 5, 23, N, 17, N, 16], target = 38
Output: 3 Explanation: 5,17,16 is the smallest subtree with length 3.
Input: root = [7, N, 23, 10, 23, N, 17], target = 73
Output: -1 Explanation: No subtree is BST for the given target.
[Naive Approach] Check Every Subtree Independently - O(n^2) Time and O(h) Space
Treat every node as a potential subtree root and independently check whether its subtree is a BST using min-max validation.
If valid, compute its sum and size, and track the minimum size for subtrees matching the target sum.
Illustration:
Take root = [13, 5, 23, N, 17, N, 16], target = 38.
Checking the subtree rooted at 5 (containing 5, 17, 16): this is validated as a BST (5 < 17, and 16 < 17 fits correctly as 17's left child), with sum = 5+17+16 = 38, matching the target, and size = 3.
Checking the subtree rooted at 13 (the whole tree): this is not a valid BST, since 23 (in 13's right subtree) is fine, but node 17 sits in 13's left subtree while also needing to be less than 23 and greater than 5 - the actual violation is that 16 and 17 don't fit BST ordering relative to the whole tree's structure at node 5, since 5's right child 17 having a left child 16 disrupts the BST property when checked against the full tree's range.
Checking other individual nodes (13, 23, 16, etc.) as subtree roots either fails the BST check or doesn't match the target sum.
Among all valid BST subtrees checked, the one rooted at 5 gives the smallest matching size of 3, matching the expected output.
C++
#include<bits/stdc++.h>usingnamespacestd;classNode{public:intdata;Node*left,*right;Node(intval){data=val;left=right=nullptr;}};boolisBST(Node*node,longlonglo,longlonghi){if(node==nullptr)returntrue;if(node->data<=lo||node->data>=hi)returnfalse;returnisBST(node->left,lo,node->data)&&isBST(node->right,node->data,hi);}intsumOfSubtree(Node*node){if(node==nullptr)return0;returnnode->data+sumOfSubtree(node->left)+sumOfSubtree(node->right);}intsizeOfSubtree(Node*node){if(node==nullptr)return0;return1+sizeOfSubtree(node->left)+sizeOfSubtree(node->right);}voidcollectAllNodes(Node*node,vector<Node*>&nodes){if(node==nullptr)return;nodes.push_back(node);collectAllNodes(node->left,nodes);collectAllNodes(node->right,nodes);}intminSubtreeSumBST(inttarget,Node*root){vector<Node*>allNodes;collectAllNodes(root,allNodes);intbest=INT_MAX;// check every node as a potential subtree root independentlyfor(Node*node:allNodes){if(isBST(node,LLONG_MIN,LLONG_MAX)){intsum=sumOfSubtree(node);if(sum==target){best=min(best,sizeOfSubtree(node));}}}return(best==INT_MAX)?-1:best;}intmain(){Node*root=newNode(13);root->left=newNode(5);root->right=newNode(23);root->left->right=newNode(17);root->left->right->left=newNode(16);cout<<minSubtreeSumBST(38,root)<<endl;return0;}
Java
importjava.util.*;classNode{intdata;Nodeleft,right;Node(intval){data=val;left=right=null;}}classGFG{staticbooleanisBST(Nodenode,longlo,longhi){if(node==null)returntrue;if(node.data<=lo||node.data>=hi)returnfalse;returnisBST(node.left,lo,node.data)&&isBST(node.right,node.data,hi);}staticintsumOfSubtree(Nodenode){if(node==null)return0;returnnode.data+sumOfSubtree(node.left)+sumOfSubtree(node.right);}staticintsizeOfSubtree(Nodenode){if(node==null)return0;return1+sizeOfSubtree(node.left)+sizeOfSubtree(node.right);}staticvoidcollectAllNodes(Nodenode,List<Node>nodes){if(node==null)return;nodes.add(node);collectAllNodes(node.left,nodes);collectAllNodes(node.right,nodes);}staticintminSubtreeSumBST(inttarget,Noderoot){List<Node>allNodes=newArrayList<>();collectAllNodes(root,allNodes);intbest=Integer.MAX_VALUE;// check every node as a potential subtree root independentlyfor(Nodenode:allNodes){if(isBST(node,Long.MIN_VALUE,Long.MAX_VALUE)){intsum=sumOfSubtree(node);if(sum==target){best=Math.min(best,sizeOfSubtree(node));}}}return(best==Integer.MAX_VALUE)?-1:best;}publicstaticvoidmain(String[]args){Noderoot=newNode(13);root.left=newNode(5);root.right=newNode(23);root.left.right=newNode(17);root.left.right.left=newNode(16);System.out.println(minSubtreeSumBST(38,root));}}
Python
importsysclassNode:def__init__(self,val):self.data=valself.left=Noneself.right=NonedefisBST(node,lo,hi):ifnodeisNone:returnTrueifnode.data<=loornode.data>=hi:returnFalsereturnisBST(node.left,lo,node.data)andisBST(node.right,node.data,hi)defsumOfSubtree(node):ifnodeisNone:return0returnnode.data+sumOfSubtree(node.left)+sumOfSubtree(node.right)defsizeOfSubtree(node):ifnodeisNone:return0return1+sizeOfSubtree(node.left)+sizeOfSubtree(node.right)defcollectAllNodes(node,nodes):ifnodeisNone:returnnodes.append(node)collectAllNodes(node.left,nodes)collectAllNodes(node.right,nodes)defminSubtreeSumBST(target,root):all_nodes=[]collectAllNodes(root,all_nodes)best=sys.maxsize# check every node as a potential subtree root independentlyfornodeinall_nodes:ifisBST(node,-sys.maxsize,sys.maxsize):total=sumOfSubtree(node)iftotal==target:best=min(best,sizeOfSubtree(node))return-1ifbest==sys.maxsizeelsebestroot=Node(13)root.left=Node(5)root.right=Node(23)root.left.right=Node(17)root.left.right.left=Node(16)print(minSubtreeSumBST(38,root))
C#
usingSystem;usingSystem.Collections.Generic;classNode{publicintdata;publicNodeleft,right;publicNode(intval){data=val;left=right=null;}}classGFG{staticboolisBST(Nodenode,longlo,longhi){if(node==null)returntrue;if(node.data<=lo||node.data>=hi)returnfalse;returnisBST(node.left,lo,node.data)&&isBST(node.right,node.data,hi);}staticintsumOfSubtree(Nodenode){if(node==null)return0;returnnode.data+sumOfSubtree(node.left)+sumOfSubtree(node.right);}staticintsizeOfSubtree(Nodenode){if(node==null)return0;return1+sizeOfSubtree(node.left)+sizeOfSubtree(node.right);}staticvoidcollectAllNodes(Nodenode,List<Node>nodes){if(node==null)return;nodes.Add(node);collectAllNodes(node.left,nodes);collectAllNodes(node.right,nodes);}staticintminSubtreeSumBST(inttarget,Noderoot){List<Node>allNodes=newList<Node>();collectAllNodes(root,allNodes);intbest=int.MaxValue;// check every node as a potential subtree root independentlyforeach(NodenodeinallNodes){if(isBST(node,long.MinValue,long.MaxValue)){intsum=sumOfSubtree(node);if(sum==target){best=Math.Min(best,sizeOfSubtree(node));}}}return(best==int.MaxValue)?-1:best;}staticvoidMain(){Noderoot=newNode(13);root.left=newNode(5);root.right=newNode(23);root.left.right=newNode(17);root.left.right.left=newNode(16);Console.WriteLine(minSubtreeSumBST(38,root));}}
JavaScript
classNode{constructor(val){this.data=val;this.left=null;this.right=null;}}functionisBST(node,lo,hi){if(node===null)returntrue;if(node.data<=lo||node.data>=hi)returnfalse;returnisBST(node.left,lo,node.data)&&isBST(node.right,node.data,hi);}functionsumOfSubtree(node){if(node===null)return0;returnnode.data+sumOfSubtree(node.left)+sumOfSubtree(node.right);}functionsizeOfSubtree(node){if(node===null)return0;return1+sizeOfSubtree(node.left)+sizeOfSubtree(node.right);}functioncollectAllNodes(node,nodes){if(node===null)return;nodes.push(node);collectAllNodes(node.left,nodes);collectAllNodes(node.right,nodes);}functionminSubtreeSumBST(target,root){constallNodes=[];collectAllNodes(root,allNodes);letbest=Infinity;// check every node as a potential subtree root independentlyfor(constnodeofallNodes){if(isBST(node,-Infinity,Infinity)){constsum=sumOfSubtree(node);if(sum===target){best=Math.min(best,sizeOfSubtree(node));}}}return(best===Infinity)?-1:best;}// Driver Codeconstroot=newNode(13);root.left=newNode(5);root.right=newNode(23);root.left.right=newNode(17);root.left.right.left=newNode(16);console.log(minSubtreeSumBST(38,root));
Output
3
[Expected Approach] Single-Pass Postorder Traversal - O(n) Time and O(h) Space
A single postorder traversal computes all required information for every node using its children's results.
Each node is processed in constant time, checking BST validity, minimum, maximum, sum, and size.
Illustration:
Take root = [13, 5, 23, N, 17, N, 16], target = 38.
At the leaf node 16: it's trivially a valid BST, with min=16, max=16, sum=16, size=1.
At node 17 (with left child 16): since 16 < 17, this forms a valid BST; combining gives min=16, max=17, sum=16+17=33, size=2.
At node 5 (with right child being the subtree rooted at 17): since 5 < 17 (the minimum of the right subtree), this forms a valid BST; combining gives min=5, max=17, sum=5+33=38, size=3. Since this sum exactly matches the target, the answer is updated to 3.
At node 23: trivially a valid BST on its own, sum=23, size=1, not matching the target.
At the root 13: combining the left subtree (rooted at 5, valid BST with max=17) and right subtree (rooted at 23, valid BST with min=23) requires checking that 13 is greater than the left subtree's max (17) — but 13 < 17, so this fails the BST condition, meaning the whole tree is not a valid BST.
Since the smallest valid BST subtree found with sum 38 is the one rooted at 5, with size 3, this is the final answer.
C++
#include<bits/stdc++.h>usingnamespacestd;classNode{public:intdata;Node*left,*right;Node(intval){data=val;left=right=nullptr;}};intans;// Returns: {isBST, min, max, sum, size}vector<int>dfs(Node*root,inttarget){if(root==nullptr)return{1,INT_MAX,INT_MIN,0,0};vector<int>left=dfs(root->left,target);vector<int>right=dfs(root->right,target);intsum=left[3]+right[3]+root->data;intsize=left[4]+right[4]+1;// check if current subtree is a BSTif(left[0]&&right[0]&&root->data>left[2]&&root->data<right[1]){// update minimum size for matching sumif(sum==target)ans=min(ans,size);intmn=min(root->data,left[1]);intmx=max(root->data,right[2]);return{1,mn,mx,sum,size};}// current subtree is not a BSTreturn{0,INT_MIN,INT_MAX,sum,size};}intminSubtreeSumBST(inttarget,Node*root){ans=INT_MAX;dfs(root,target);return(ans==INT_MAX)?-1:ans;}intmain(){Node*root=newNode(13);root->left=newNode(5);root->right=newNode(23);root->left->right=newNode(17);root->left->right->left=newNode(16);cout<<minSubtreeSumBST(38,root)<<endl;return0;}
importsysclassNode:def__init__(self,val):self.data=valself.left=Noneself.right=NonedefminSubtreeSumBST(target,root):ans=[sys.maxsize]# returns (isBST, minVal, maxVal, sum, size)defdfs(node):ifnodeisNone:return(1,sys.maxsize,-sys.maxsize,0,0)left=dfs(node.left)right=dfs(node.right)total=left[3]+right[3]+node.datasize=left[4]+right[4]+1# check if current subtree is a BSTifleft[0]andright[0]andnode.data>left[2]andnode.data<right[1]:# update minimum size for matching sumiftotal==target:ans[0]=min(ans[0],size)mn=min(node.data,left[1])mx=max(node.data,right[2])return(1,mn,mx,total,size)# current subtree is not a BSTreturn(0,-sys.maxsize,sys.maxsize,total,size)dfs(root)return-1ifans[0]==sys.maxsizeelseans[0]root=Node(13)root.left=Node(5)root.right=Node(23)root.left.right=Node(17)root.left.right.left=Node(16)print(minSubtreeSumBST(38,root))