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:
    1. getPredecessor(N), which returns the next smaller node to N.
    2. 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.

Solution:

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode(int x) { val = x; }
  8. * }
  9. */
  10. public class Solution {
  11. public List<Integer> closestKValues(TreeNode root, double target, int k) {
  12. List<Integer> res = new ArrayList<>();
  13. Stack<Integer> s1 = inorder(root, target, true); // predecessors
  14. Stack<Integer> s2 = inorder(root, target, false); // successors
  15. while (k-- > 0) {
  16. if (s1.isEmpty())
  17. res.add(s2.pop());
  18. else if (s2.isEmpty())
  19. res.add(s1.pop());
  20. else if (Math.abs(s1.peek() - target) < Math.abs(s2.peek() - target))
  21. res.add(s1.pop());
  22. else
  23. res.add(s2.pop());
  24. }
  25. return res;
  26. }
  27. // iterative inorder traversal
  28. Stack<Integer> inorder(TreeNode root, double target, boolean reverse) {
  29. Stack<Integer> res = new Stack<>();
  30. Stack<TreeNode> stack = new Stack<>();
  31. TreeNode curr = root;
  32. while (!stack.isEmpty() || curr != null) {
  33. if (curr != null) {
  34. stack.push(curr);
  35. curr = reverse ? curr.right : curr.left;
  36. } else {
  37. curr = stack.pop();
  38. if (reverse && curr.val <= target) break;
  39. if (!reverse && curr.val > target) break;
  40. res.push(curr.val);
  41. curr = reverse ? curr.left : curr.right;
  42. }
  43. }
  44. return res;
  45. }
  46. }