package com.interview.tree; import java.util.ArrayList; import java.util.List; import java.util.Stack; /** * Date 10/08/2016 * @author Tushar Roy * * Given a non-empty binary search tree and a target value, find k values in the BST that are closest to the target. * * Time complexity O(log(n) + k) * * https://leetcode.com/problems/closest-binary-search-tree-value-ii/ */ public class KClosestValueInBinaryTree { public List<Integer> closestKValues(Node root, double target, int k) { if (root == null || k == 0) { return new ArrayList<>(); } Stack<Node> predecessor = new Stack(); Stack<Node> successor = new Stack(); double closestDiff = Double.MAX_VALUE; Node closestDiffNode = null; while (root != null) { predecessor.push(root); successor.push(root); if (Math.abs(target - root.data) < closestDiff) { closestDiff = Math.abs(target - root.data); closestDiffNode = root; } if (root.data == target) { break; } else if (target > root.data) { root = root.right; } else { root = root.left; } } while (predecessor.peek() != closestDiffNode) { predecessor.pop(); successor.pop(); } predecessor.pop(); successor.pop(); List<Integer> result = new ArrayList<>(); result.add(closestDiffNode.data); Node prec = closestDiffNode; Node succ = closestDiffNode; k--; prec = predecessor(predecessor, prec); succ = successor(successor, succ); while (k > 0) { if (succ == null || (prec != null && Math.abs(target - prec.data) < Math.abs(target - succ.data))) { result.add(prec.data); prec = predecessor(predecessor, prec); } else { result.add(succ.data); succ = successor(successor, succ); } k--; } return result; } private Node predecessor(Stack<Node> stack, Node current) { if (current == null) { return null; } if (current.left != null) { stack.push(current); current = current.left; while (current.right != null) { stack.push(current); current = current.right; } return current; } else { while (!stack.isEmpty() && stack.peek().left == current) { current = stack.pop(); } if (stack.isEmpty()) { return null; } else { return stack.pop(); } } } private Node successor(Stack<Node> stack, Node current) { if (current == null) { return null; } if (current.right != null) { stack.push(current); current = current.right; while (current.left != null) { stack.push(current); current = current.left; } return current; } else { while (!stack.isEmpty() && stack.peek().right == current) { current = stack.pop(); } if (stack.isEmpty()) { return null; } else { return stack.pop(); } } } }