272. Closest Binary Search Tree Value II - Explanation

Problem Link

Description

Given the root of a binary search tree, a target value, and an integer k, return the k values in the BST that are closest to the target. You may return the answer in any order.

You are guaranteed to have only one unique set of k values in the BST that are closest to the target.

Example 1:

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

Output: [4,3]

Example 2:

Input: root = [1], target = 0.000000, k = 1

Output: [1]

Constraints:

  • The number of nodes in the tree is n.
  • 1 <= k <= n <= 10⁴.
  • 0 <= Node.val <= 10⁹
  • -10⁹ <= target <= 10⁹

Follow up: Assume that the BST is balanced. Could you solve it in less than O(n) runtime (where n = total nodes)?


Company Tags


1. Sort With Custom Comparator

class Solution:
    def closestKValues(self, root: TreeNode, target: float, k: int) -> List[int]:
        def dfs(node, arr):
            if not node:
                return
            
            arr.append(node.val)
            dfs(node.left, arr)
            dfs(node.right, arr)
        
        arr = []
        dfs(root, arr)
        
        arr.sort(key = lambda x: (abs(x - target), x))
        return arr[:k]

Time & Space Complexity

  • Time complexity: O(nlogn)O(n \cdot \log n)
  • Space complexity: O(n)O(n)

Where nn is the number of nodes in the tree


2. Traverse With Heap

class Solution:
    def closestKValues(self, root: TreeNode, target: float, k: int) -> List[int]:
        def dfs(node, heap):
            if not node:
                return

            if len(heap) < k:
                heappush(heap, (-abs(node.val - target), node.val))
            else:
                if abs(node.val - target) <= abs(heap[0][0]):
                    heappop(heap)
                    heappush(heap, (-abs(node.val - target), node.val))

            dfs(node.left, heap)
            dfs(node.right, heap)

        heap = []
        dfs(root, heap)
        return [x[1] for x in heap]

Time & Space Complexity

  • Time complexity: O(nlogk)O(n \cdot \log k)
  • Space complexity: O(n+k)O(n+k)

Where nn is the number of nodes in the tree and kk is the size of our heap


3. Inorder Traversal + Sliding Window

class Solution:
    def closestKValues(self, root: TreeNode, target: float, k: int) -> List[int]:
        def dfs(node, arr):
            if not node:
                return
            
            dfs(node.left, arr)
            arr.append(node.val)
            dfs(node.right, arr)
        
        arr = []
        dfs(root, arr)
        
        left = bisect_left(arr, target) - 1
        right = left + 1
        ans = []
        
        while len(ans) < k:
            if right == len(arr) or abs(arr[left] - target) <= abs(arr[right] - target):
                ans.append(arr[left])
                left -= 1
            else:
                ans.append(arr[right])
                right += 1
        
        return ans

Time & Space Complexity

  • Time complexity: O(n+k)O(n+k)
  • Space complexity: O(n)O(n)

Where nn is the number of nodes in the tree and kk is the size of our sliding window


4. Binary Search The Left Bound

class Solution:
    def closestKValues(self, root: TreeNode, target: float, k: int) -> List[int]:
        def dfs(node, arr):
            if not node:
                return
            
            dfs(node.left, arr)
            arr.append(node.val)
            dfs(node.right, arr)
        
        arr = []
        dfs(root, arr)
        
        left = 0
        right = len(arr) - k
        
        while left < right:
            mid = (left + right) // 2
            if abs(target - arr[mid + k]) < abs(target - arr[mid]):
                left = mid + 1
            else:
                right = mid

        return arr[left:left + k]

Time & Space Complexity

  • Time complexity:
    • O(n)O(n) in Java
    • O(n+k)O(n+k) in Python
  • Space complexity: O(n)O(n)

Where nn is the number of nodes in the tree and kk is the number of closest values to return


5. Build The Window With Deque

class Solution:
    def closestKValues(self, root: TreeNode, target: float, k: int) -> List[int]:
        def dfs(node, queue):
            if not node:
                return
            
            dfs(node.left, queue)
            queue.append(node.val)
            if len(queue) > k:
                if (abs(target - queue[0]) <= abs(target - queue[-1])):
                    queue.pop()
                    return
                else:
                    queue.popleft()
                    
            dfs(node.right, queue)
        
        queue = deque()
        dfs(root, queue)
        return list(queue)

Time & Space Complexity

  • Time complexity: O(n)O(n)
  • Space complexity: O(n+k)O(n+k)

Where nn is the number of nodes in the tree and kk is the number of closest values to return