~/problems / Binary search / Binary search

Find K Closest Elements

medium ~30 min

A shop keeps its price points in a sorted list. Given a customer's budget x, it wants to show the k price points nearest to it.

Write nearest_values(arr: list[int], k: int, x: int) -> list[int] that returns the k values of arr closest to x, in ascending order.

  • Value a is closer than value b when |a - x| < |b - x|, or when |a - x| == |b - x| and a < b (on a tie, the smaller value wins).
  • arr is sorted in non-decreasing order and may contain repeated values; each position counts separately, so a value can appear in the answer as many times as it appears in arr.
nearest_values([1, 3, 4, 8, 10], 3, 5)     # [3, 4, 8]
nearest_values([1, 3, 4, 8, 10], 2, 6)     # [4, 8]   (4 and 8 are both 2 away)
nearest_values([2, 4, 6], 2, 5)            # [4, 6]   (4 and 6 tie at 1 away)
nearest_values([1, 2, 3], 2, 100)          # [2, 3]
nearest_values([5, 5, 5, 9], 2, 7)         # [5, 5]   (9 and 5 are both 2 away; 5 is smaller)
  • 1 <= k <= len(arr) <= 10^6; values and x are in [-10^9, 10^9]; x need not be in arr.
  • The tests ask thousands of questions about one big list with small k, so each call must be O(log n + k). Sorting by distance, or scanning the whole list, is too slow. Don't use the bisect module.
  • C++ / Java: you write nearestValuesAll(arr, queries). Each query is a pair [k, x]; return nearestValues(arr, k, x) for each, in order. Write nearestValues as a helper and call it in a loop.
Show hint

the answer is always a contiguous run of k positions in arr. Find where x would sit, then grow the run outwards one value at a time, or search directly for where the run starts.

Topic: Binary search. lo/hi invariants, lower vs upper bound, rotated arrays, bisect.

Read the visual guide
0:00
Ctrl ' run · Ctrl ↵ submit
esc