Question

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.

Example:

Input: root = [4,2,5,1,3], target = 3.714286, and k = 2

    4
   / \
  2   5
 / \
1   3

Output: [4,3]

Follow up:

Assume that the BST is balanced, could you solve it in less than O(n) runtime (where n = total nodes)?

Solution

To get an \(O(n)\) solution, first perform a DFS of the BST to get sorted values. Then build the result.

# 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]
        """
        nodeVal = list()
        self.dfs(root, nodeVal)
        if target < nodeVal[0]:
            return nodeVal[:k]
        elif target > nodeVal[-1]:
            return nodeVal[-k:]
        else:
            i = 0
            while i < len(nodeVal) - 1:
                if nodeVal[i] <= target < nodeVal[i + 1]:
                    break
                else:
                    i += 1

            res = list()
            left, right = i, i + 1
            if target - nodeVal[left] <= nodeVal[right] - target:
                left_residue = 0
            else:
                left_residue = 1
            idx = 0
            while idx < k:
                if (idx % 2 == left_residue and left >= 0) or right == len(nodeVal):
                    res.append(nodeVal[left])
                    left -= 1
                else:
                    res.append(nodeVal[right])
                    right += 1
                idx += 1

            return res


    def dfs(self, root, res):
        if root is None:
            return
        if root.left is not None:
            self.dfs(root.left, res)
        res.append(root.val)
        if root.right is not None:
            self.dfs(root.right, res)