题目:
Given a non-empty binary search tree and a target value, find k values in the BST that are closest to the target.
Note:
- Given target value is a floating point.
- You may assume k is always valid, that is: k ≤ total nodes.
- You are guaranteed to have only one unique set of k values in the BST that are closest to the target.
Follow up:
Assume that the BST is balanced, could you solve it in less than O(n) runtime (where n = total nodes)?
Hint:
- Consider implement these two helper functions:
getPredecessor(N)
, which returns the next smaller node to N.getSuccessor(N)
, which returns the next larger node to N.
- Try to assume that each node has a parent pointer, it makes the problem much easier.
- Without parent pointer we just need to keep track of the path from the root to the current node using a stack.
- You would need two stacks to track the path in finding predecessor and successor node separately.
正向Inorder + 反向Inorder。正向得到小于target的元素的顺序, 反向得到大于等于target的顺序,存于堆栈中,如target = 5.5,
正向栈得:12345,反向栈得9876,栈顶元素分别为5和6,以此比较两个栈的栈顶,加入结果中只到K个。
C++版:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> closestKValues(TreeNode* root, double target, int k) {
vector<int> results;
stack<int> incr, decr;
inOrder(root, target, false, incr);
inOrder(root, target, true, decr);
while(results.size() < k) {
if(incr.empty()) {
results.push_back(decr.top());
decr.pop();
} else if (decr.empty()) {
results.push_back(incr.top());
incr.pop();
} else if(abs(incr.top() - target) < abs(decr.top() - target)) {
results.push_back(incr.top());
incr.pop();
} else {
results.push_back(decr.top());
decr.pop();
}
}
return results;
}
void inOrder(TreeNode* root, double target, bool reverse, stack<int> &order) {
if(root == NULL)
return;
inOrder(reverse ? root->right : root->left, target, reverse, order);
if((reverse && root->val <= target) || (!reverse && root->val > target))
return;
order.push(root->val);
inOrder(reverse ? root->left : root->right, target, reverse, order);
}
};
Java版:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public List<Integer> closestKValues(TreeNode root, double target, int k) {
List<Integer> results = new ArrayList<>();
Stack<Integer> incr = new Stack<>();
Stack<Integer> decr = new Stack<>();
inOrder(root, target, false, incr);
inOrder(root, target, true, decr);
while(k != 0) {
if(incr.empty()) {
results.add(decr.pop());
} else if (decr.empty()) {
results.add(incr.pop());
} else if(Math.abs(incr.peek() - target) > Math.abs(decr.peek() - target)) {
results.add(decr.pop());
} else {
results.add(incr.pop());
}
k--;
}
return results;
}
void inOrder(TreeNode root, double target, boolean reverse, Stack<Integer> order) {
if(root == null)
return;
inOrder(reverse ? root.right : root.left, target, reverse, order);
if((reverse && root.val <= target) || (!reverse && root.val > target))
return;
order.push(root.val);
inOrder(reverse ? root.left : root.right, target, reverse, order);
}
}
Python版:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def closestKValues(self, root, target, k):
"""
:type root: TreeNode
:type target: float
:type k: int
:rtype: List[int]
"""
incr, decr = [], []
self.inOrder(root, target, False, incr)
self.inOrder(root, target, True, decr)
results = []
while len(results) < k:
if len(incr) == 0:
results.append(decr.pop())
elif len(decr) == 0:
results.append(incr.pop())
elif abs(incr[-1] - target) < abs(decr[-1] - target):
results.append(incr.pop())
else:
results.append(decr.pop())
return results
def inOrder(self, root, target, reverse, order):
if root == None:
return
if reverse:
self.inOrder(root.right, target, reverse, order)
else:
self.inOrder(root.left, target, reverse, order)
if (reverse and root.val < target) or (not reverse and root.val >= target):
return
order.append(root.val)
if reverse:
self.inOrder(root.left, target, reverse, order)
else:
self.inOrder(root.right, target, reverse, order)