Given a non-empty binary search tree and a target value, find K values in the BST that is closest to the target.
Note:
- Given target value is a floating point.
- Assume k is always valid, which is: k ≤total nodes.
- You is guaranteed to a unique set of K values in the BST is closest to the target.
Follow up:
Assume that the BST are balanced, could you solve it in less than O(n) runtime (where n = Total nodes)?
Hint:
1. Consider implement these the helper functions:
I. Getpredecessor (N), which returns the next smaller node to N.
II. Getsuccessor (N), which returns the next larger node to N.
2. Try to assume this each node has a parent pointer, it makes the problem much easier.
3. Without parent pointer we just need to keep track of the path from the root to the current node using a stack.
4. You would need-stacks to track the path in finding predecessor and successor node separately.
This question is the extension of the previous closest Binary Search Tree value, which only allows us to find a node value closest to the target value, which allows us to find the nearest K node value from the target value, the difficulty instantly increases a lot, My first thought was to use the middle sequence traversal to store all the node values in a one-dimensional array, and because of the nature of the binary search tree, this one-dimensional array is ordered, and then we need the nearest K-values in the ordered array and the target values to be much simpler, see the code below:
Solution One:
classSolution { Public: Vector<int> closestkvalues (treenode* root,DoubleTargetintk) {vector<int>Res, V; Inorder (Root, v); intIDX =0; Doublediff = numeric_limits<Double>:: Max (); for(inti =0; I < v.size (); ++i) {if(diff >= Abs (Target-V[i])) {diff= ABS (Target-V[i]); IDX=i; } } intleft = idx-1, right = idx +1; for(inti =0; I < K; ++i) {res.push_back (v[idx]); if(Left >=0&& Right <v.size ()) { if(ABS (V[left]-target) > abs (V[right]-target)) {idx=Right ; ++Right ; } Else{idx=Left ; --Left ; } } Else if(Left >=0) {idx=Left ; --Left ; } Else if(Right <v.size ()) {idx=Right ; ++Right ; } } returnRes; } voidInorder (TreeNode *root, vector<int> &v) {if(!root)return; Inorder (Root-Left , v); V.push_back (Root-val); Inorder (Root-Right , V); }};
There is also a solution is directly in the middle sequence traversal process to complete the comparison, when traversing to a node, if the result array is less than k, we directly add this node value to the Res, if the difference between the value of the node and the target value of the absolute value is less than the first element of the res and the value of the target difference, the current value , the first element is deleted, the end is added to the current node value, and conversely, the current value is more deviation from the target value than all the values in res, due to the characteristics of the sequential traversal, then the value will be more traversed, so this time directly return the final result, see the code is as follows:
Solution Two:
classSolution { Public: Vector<int> closestkvalues (treenode* root,DoubleTargetintk) {vector<int>Res; Inorder (root, Target, K, res); returnRes; } voidInorder (TreeNode *root,DoubleTargetintK, vector<int> &Res) { if(!root)return; Inorder (Root-Left , Target, K, res); if(Res.size () < K) Res.push_back (root->val); Else if(ABS (Root->val-target) < ABS (res[0] -target)) {Res.erase (Res.begin ()); Res.push_back (Root-val); } Else return; Inorder (Root-Right , Target, K, res); }};
The following method is the iterative way of the above method, the same principle, see the code is as follows:
Solution Three:
classSolution { Public: Vector<int> closestkvalues (treenode* root,DoubleTargetintk) {vector<int>Res; Stack<TreeNode*>s; TreeNode*p =Root; while(P | |!S.empty ()) { while(P) {S.push (P); P= p->Left ; } P=s.top (); S.pop (); if(Res.size () < K) Res.push_back (p->val); Else if(ABS (P->val-target) < ABS (res[0] -target)) {Res.erase (Res.begin ()); Res.push_back (P-val); } Else Break; P= p->Right ; } returnRes; }};
In order to solve a problem using the largest heap, a pair of difference diff and node values stored in the heap, we traverse the binary tree (or other traversal methods), and then calculate the absolute value of the difference between the values of each node and the target value, due to the nature of the maximum heap, diff big Automatic shot to the front, We maintain the k pair, if more than K, the big pair in front of the heap is deleted, the last left of the K pair, we will be in the pair of the node value out into the res return can be, see the code is as follows:
Solution Four:
classSolution { Public: Vector<int> closestkvalues (treenode* root,DoubleTargetintk) {vector<int>Res; Priority_queue<pair<Double,int>>Q; Inorder (root, Target, K, q); while(!Q.empty ()) {Res.push_back (Q.top (). second); Q.pop (); } returnRes; } voidInorder (TreeNode *root,DoubleTargetintK, priority_queue<pair<Double,int>> &q) {if(!root)return; Inorder (Root-Left , Target, K, q); Q.push ({abs (Root->val-target), root->val}); if(Q.size () >k) Q.pop (); Inorder (Root-Right , Target, K, q); }};
The following method uses two stacks, pre and suc, where the pre is less than the number of target values, suc is larger than the target value, start initializing the pre and suc, respectively, the closest to the target value of the slightly smaller value and slightly larger value into the pre and suc, and then we loop k times, Compare the top elements of the pre and suc each time to see who is closer to the target value, save it in the result res, and then update the stack of the extracted elements, and so on until the number of K is returned, see the code below:
Solution Five:
classSolution { Public: Vector<int> closestkvalues (treenode* root,DoubleTargetintk) {vector<int>Res; Stack<TreeNode*>Pre, suc; while(root) {if(Root->val <=target) {Pre.push (root); Root= root->Right ; } Else{Suc.push (root); Root= root->Left ; } } while(k-->0) { if(Suc.empty () | |!pre.empty () && target-pre.top ()->val < Suc.top ()->val-target) {Res.push_back (Pre.top ()-val); Getpredecessor (pre); } Else{res.push_back (suc.top ()-val); Getsuccessor (SUC); } } returnRes; } voidGetpredecessor (Stack<treenode*> &pre) {TreeNode*t =pre.top (); Pre.pop (); if(t->Left ) {Pre.push (t-Left ); while(Pre.top ()->right) Pre.push (Pre.top ()Right ); } } voidGetsuccessor (Stack<treenode*> &suc) {TreeNode*t =suc.top (); Suc.pop (); if(t->Right ) {Suc.push (t-Right ); while(Suc.top ()->left) Suc.push (Suc.top ()Left ); } }};
Similar topics:
Closest Binary Search Tree Value
Resources:
Https://leetcode.com/discuss/69220/2-ms-o-n-and-6-ms-o-logn-java-solution
Https://leetcode.com/discuss/77954/easy-o-n-c-solution-using-priority_queue
Https://leetcode.com/discuss/64713/clear-java-solution-with-one-stack-one-linkedlist
Https://leetcode.com/discuss/83431/c-simple-inorder-solution-with-o-n-runtime-and-o-k-memory
Leetcode all in one topic summary (continuous update ...)
[Leetcode] Closest binary search Tree Value II the values of the nearest binary trees