270: Closest Binary Search Tree Value II
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.
https://leetcode.com/discuss/69220/2-ms-o-n-and-6-ms-o-logn-java-solution
O(lgN):
public class Solution {
public List<Integer> closestKValues(TreeNode root, double target, int k) {
LinkedList<Integer> list = new LinkedList<Integer>();
closestKValuesHelper(list, root, target, k);
return list;
}
/**
* @return <code>true</code> if result is already found.
*/
private boolean closestKValuesHelper(LinkedList<Integer> list, TreeNode root, double target, int k) {
if (root == null) {
return false;
}
if (closestKValuesHelper(list, root.left, target, k)) {
return true;
}
if (list.size() == k) {
if (Math.abs(list.getFirst() - target) < Math.abs(root.val - target)) {
return true;
} else {
list.removeFirst();
}
}
list.addLast(root.val);
return closestKValuesHelper(list, root.right, target, k);
}
}
O(lgN):
public List<Integer> closestKValues(TreeNode root, double target, int k) {
List<Integer> list = new ArrayList<>();
Stack<TreeNode> pred = new Stack<>(), succ = new Stack<>();
initStack(pred, succ, root, target);
while(k-- > 0){
if(succ.isEmpty() || !pred.isEmpty() && target - pred.peek().val < succ.peek().val - target){
list.add(pred.peek().val);
getPredecessor(pred);
}
else{//Since N > k, always have something to add
list.add(succ.peek().val);
getSuccessor(succ);
}
}
return list;
}
private void initStack(Stack<TreeNode> pred, Stack<TreeNode> succ, TreeNode root, double target){
while(root != null){
if(root.val <= target){
pred.push(root);
root = root.right;
}
else{
succ.push(root);
root = root.left;
}
}
}
private void getPredecessor(Stack<TreeNode> st){
TreeNode node = st.pop();
if(node.left != null){
st.push(node.left);
while(st.peek().right != null) st.push(st.peek().right);
}
}
private void getSuccessor(Stack<TreeNode> st){
TreeNode node = st.pop();
if(node.right != null){
st.push(node.right);
while(st.peek().left != null) st.push(st.peek().left);
}
}
public class Solution {
public List<Integer> closestKValues(TreeNode root, double target, int k) {
List<Integer> result = new ArrayList<>();
if (root == null) {
return result;
}
Stack<Integer> precedessor = new Stack<>();
Stack<Integer> successor = new Stack<>();
getPredecessor(root, target, precedessor);
getSuccessor(root, target, successor);
for (int i = 0; i < k; i++) {
if (precedessor.isEmpty()) {
result.add(successor.pop());
} else if (successor.isEmpty()) {
result.add(precedessor.pop());
} else if (Math.abs((double) precedessor.peek() - target) < Math.abs((double) successor.peek() - target)) {
result.add(precedessor.pop());
} else {
result.add(successor.pop());
}
}
return result;
}
private void getPredecessor(TreeNode root, double target, Stack<Integer> precedessor) {
if (root == null) {
return;
}
getPredecessor(root.left, target, precedessor);
if (root.val > target) {
return;
}
precedessor.push(root.val);
getPredecessor(root.right, target, precedessor);
}
private void getSuccessor(TreeNode root, double target, Stack<Integer> successor) {
if (root == null) {
return;
}
getSuccessor(root.right, target, successor);
if (root.val <= target) {
return;
}
successor.push(root.val);
getSuccessor(root.left, target, successor);
}
}