Given the root node of a binary search tree (BST) and a target value. The task is to find the k values in the BST that are closest to the target value. The answer can be returned in any order. It is guaranteed that there is only one unique set of k values in the BST that are closest to the target.
Example:
Input: root = [5,3,6,2,4], target = 3.714286, k = 2
The idea is to perform an any traversal on the BST, during which the absolute difference between each node's value and the target is calculated. These differences are stored in a max heap along with their corresponding node values. The heap is structured such that it retains only the k smallest differences (closest values) by discarding the largest difference whenever the heap's size exceeds k. This ensures that, at the end of the traversal, the heap contains the k values with the smallest distances to the target. The values are then extracted from the heap to form the final result. This method efficiently narrows down the closest values in a single traversal, making good use of the properties of BST and max heap.
Steps-by-step approach:
Start at the root of the BST.
Calculate the distance of the current node's value from the target.
Push this (distance, value) pair onto the max heap.
If the heap size exceeds k, remove the element with the largest distance (farthest from the target). This ensures we keep the k closest values.
Recursively explore the left and right subtrees
After traversing the entire tree, the max heap will contain the k closest values. We extract these values from the heap and return them as the result.
Below is the implementation of the above approach:
C++
#include<bits/stdc++.h>usingnamespacestd;structTreeNode{intval;TreeNode*left;TreeNode*right;TreeNode():val(0),left(nullptr),right(nullptr){}TreeNode(intx):val(x),left(nullptr),right(nullptr){}TreeNode(intx,TreeNode*left,TreeNode*right):val(x),left(left),right(right){}};// Max heap to store the k closest values and their// distances from the target.priority_queue<pair<double,int>>maxH;// Recursive helper function to traverse the tree and find// the closest values.voidsolve(TreeNode*root,doubletarget,intk){if(root==nullptr){return;}// Calculate the distance from the current node's value// to the target.doubledistanceFromTarget=abs((double)root->val-target);// Push the node's value and distance onto the max heap.maxH.push({distanceFromTarget,root->val});// If the heap size exceeds k, remove the element with// the largest distance.if(maxH.size()>k){maxH.pop();}// Recursively explore the left and right subtrees.solve(root->left,target,k);solve(root->right,target,k);}// Function to find the k closest values in a binary search// tree to a given target.vector<int>closestKValues(TreeNode*root,doubletarget,intk){// Clear the max heap before each call.maxH=priority_queue<pair<double,int>>();// Traverse the tree and find the closest values.solve(root,target,k);// Extract the k closest values from the max heap and// store them in a vector.vector<int>result;while(!maxH.empty()){result.push_back(maxH.top().second);maxH.pop();}// Return the vector of k closest values.returnresult;}intmain(){/* Let's create the following BST: 5 / \ 3 6 / \ 2 4 */TreeNode*root=newTreeNode(5);root->left=newTreeNode(3);root->right=newTreeNode(6);root->left->left=newTreeNode(2);root->left->right=newTreeNode(4);doubletarget=3.714286;intk=2;vector<int>result=closestKValues(root,target,k);cout<<"The closest "<<k<<" values to "<<target<<" are: ";for(intval:result){cout<<val<<" ";}cout<<endl;return0;}
Java
importjava.util.ArrayList;importjava.util.List;importjava.util.PriorityQueue;classTreeNode{intval;TreeNodeleft;TreeNoderight;TreeNode(){}TreeNode(intval){this.val=val;}TreeNode(intval,TreeNodeleft,TreeNoderight){this.val=val;this.left=left;this.right=right;}}publicclassClosestKValuesBST{// Max heap to store the k closest values and their// distances from the target.staticPriorityQueue<Pair<Double,Integer>>maxH;// Recursive helper function to traverse the tree and// find the closest values.staticvoidsolve(TreeNoderoot,doubletarget,intk){if(root==null){return;}// Calculate the distance from the current node's// value to the target.doubledistanceFromTarget=Math.abs((double)root.val-target);// Push the node's value and distance onto the max// heap.maxH.offer(newPair<>(distanceFromTarget,root.val));// If the heap size exceeds k, remove the element// with the largest distance.if(maxH.size()>k){maxH.poll();}// Recursively explore the left and right subtrees.solve(root.left,target,k);solve(root.right,target,k);}// Function to find the k closest values in a binary// search tree to a given target.staticList<Integer>closestKValues(TreeNoderoot,doubletarget,intk){// Initialize the max heap.maxH=newPriorityQueue<>((a,b)->Double.compare(b.getKey(),a.getKey()));// Traverse the tree and find the closest values.solve(root,target,k);// Extract the k closest values from the max heap// and store them in a list.List<Integer>result=newArrayList<>();while(!maxH.isEmpty()){result.add(maxH.poll().getValue());}// Return the list of k closest values.returnresult;}publicstaticvoidmain(String[]args){/* Let's create the following BST: 5 / \ 3 6 / \ 2 4 */TreeNoderoot=newTreeNode(5);root.left=newTreeNode(3);root.right=newTreeNode(6);root.left.left=newTreeNode(2);root.left.right=newTreeNode(4);doubletarget=3.714286;intk=2;List<Integer>result=closestKValues(root,target,k);System.out.print("The closest "+k+" values to "+target+" are: ");for(intval:result){System.out.print(val+" ");}System.out.println();}// Pair class for storing distance and valuestaticclassPair<K,V>{privatefinalKkey;privatefinalVvalue;publicPair(Kkey,Vvalue){this.key=key;this.value=value;}publicKgetKey(){returnkey;}publicVgetValue(){returnvalue;}}}
Python
importheapqclassTreeNode:def__init__(self,x,left=None,right=None):self.val=xself.left=leftself.right=right# Max heap to store the k closest values and their distances from the target.maxH=[]# Recursive helper function to traverse the tree and find the closest values.defsolve(root,target,k):ifrootisNone:return# Calculate the distance from the current node's value to the target.distanceFromTarget=abs(root.val-target)# Push the node's value and distance onto the max heap.heapq.heappush(maxH,(-distanceFromTarget,root.val))# If the heap size exceeds k, remove the element with the largest distance.iflen(maxH)>k:heapq.heappop(maxH)# Recursively explore the left and right subtrees.solve(root.left,target,k)solve(root.right,target,k)# Function to find the k closest values in a binary search tree to a given target.defclosestKValues(root,target,k):# Clear the max heap before each call.maxH.clear()# Traverse the tree and find the closest values.solve(root,target,k)# Extract the k closest values from the max heap and store them in a list.result=[valfordistance,valinmaxH]# Return the list of k closest values.returnresult''' Let's create the following BST: 5 / \ 3 6 / \ 2 4'''root=TreeNode(5)root.left=TreeNode(3)root.right=TreeNode(6)root.left.left=TreeNode(2)root.left.right=TreeNode(4)target=3.714286k=2result=closestKValues(root,target,k)print(f"The closest {k} values to {target} are: {' '.join(map(str,result))}")
JavaScript
// TreeNode class to represent nodes in the BSTclassTreeNode{constructor(val,left=null,right=null){this.val=val;this.left=left;this.right=right;}}// Pair class for storing distance and valueclassPair{constructor(key,value){this.key=key;this.value=value;}getKey(){returnthis.key;}getValue(){returnthis.value;}}// Function to find the k closest values in a binary search tree to a given targetfunctionclosestKValues(root,target,k){// Max heap to store the k closest values and their distances from the targetconstmaxHeap=newPriorityQueue((a,b)=>b.key-a.key);// Recursive helper function to traverse the tree and find the closest valuesfunctionsolve(node){if(!node){return;}// Calculate the distance from the current node's value to the targetconstdistanceFromTarget=Math.abs(node.val-target);// Push the node's value and distance onto the max heapmaxHeap.push(newPair(distanceFromTarget,node.val));// If the heap size exceeds k, remove the element with the largest distanceif(maxHeap.size()>k){maxHeap.pop();}// Recursively explore the left and right subtreessolve(node.left);solve(node.right);}// Traverse the tree and find the closest valuessolve(root);// Extract the k closest values from the max heap and store them in a listconstresult=[];while(!maxHeap.isEmpty()){result.push(maxHeap.pop().value);}// Return the list of k closest valuesreturnresult;}// Implementation of PriorityQueue in JavaScriptclassPriorityQueue{constructor(comparator=(a,b)=>a-b){this.comparator=comparator;this.heap=[];}size(){returnthis.heap.length;}isEmpty(){returnthis.size()===0;}push(val){this.heap.push(val);this.bubbleUp();}pop(){if(this.isEmpty()){returnnull;}this.swap(0,this.size()-1);constremoved=this.heap.pop();this.bubbleDown();returnremoved;}peek(){returnthis.isEmpty()?null:this.heap[0];}bubbleUp(){letindex=this.size()-1;while(index>0){constparentIndex=Math.floor((index-1)/2);if(this.comparator(this.heap[index],this.heap[parentIndex])<0){this.swap(index,parentIndex);index=parentIndex;}else{break;}}}bubbleDown(){letindex=0;while(index<this.size()){constleftChild=2*index+1;constrightChild=2*index+2;letsmallerChild=leftChild;if(rightChild<this.size()&&this.comparator(this.heap[rightChild],this.heap[leftChild])<0){smallerChild=rightChild;}if(leftChild>=this.size()||this.comparator(this.heap[index],this.heap[smallerChild])<=0){break;}this.swap(index,smallerChild);index=smallerChild;}}swap(i,j){[this.heap[i],this.heap[j]]=[this.heap[j],this.heap[i]];}}// Example usageconstroot=newTreeNode(5);root.left=newTreeNode(3);root.right=newTreeNode(6);root.left.left=newTreeNode(2);root.left.right=newTreeNode(4);consttarget=3.714286;constk=2;constresult=closestKValues(root,target,k);console.log(`The closest ${k} values to ${target} are: ${result.join(' ')}`);
Output
The closest 2 values to 3.71429 are: 3 4
Time Complexity: O(N * log K) Auxiliary Space: O(K)