Browse curriculum

Find K Closest Elements

Find k closest integers to a given value x.

Problem Understanding

From the sorted integer array arr, pick the k values nearest to x.

If |a - x| == |b - x|, the smaller number is chosen. The result should be sorted in ascending order.

Example:

  • Input: arr = [1,2,3,4,5], k = 4, x = 3
  • Output: [1,2,3,4]

Algorithm Strategy

The heap baseline — O(n log k). Treat it like any top-k problem: push every value onto a max-heap keyed by (|value − x|, value) and pop whenever it holds more than k. It works on any array, sorted or not.

A sorted array does better — O(n). Distance from x only falls and then rises along a sorted array, so the k closest values are one contiguous run, and the farther end of any window is its farthest value. Start with the whole array as the window [L, R] and shrink it:

  1. While the window holds more than k values, compare its two ends.
  2. If arr[L] is strictly farther from x than arr[R], drop L.
  3. Otherwise drop R — on a tie the smaller value, arr[L], is the one to keep.
  4. Return arr[L..R].

Binary search can find where the window starts in O(log(n − k)); the shrink is the simplest correct version, and it is what the code below does.

Interactive Visualization

The window [L, R] starts as the whole array, with each value's distance from x beneath it. Its two ends are compared and the farther one is dropped until k values remain.

Dry Run (Two Pointers)

Input: arr = [1, 2, 3, 4, 5], k = 4, x = 3

Step L R abs(arr[L] − x) abs(arr[R] − x) Action
1 0 4 2 2 A tie: keep the smaller 1, drop 5 (R = 3)
2 0 3 - - 4 values = k: stop

Result: [1, 2, 3, 4]

Input: arr = [1, 2, 3, 4, 5, 6, 7], k = 3, x = 5

Step L R abs(arr[L] − x) abs(arr[R] − x) Action
1 0 6 4 2 Drop 1 (L = 1)
2 1 6 3 2 Drop 2 (L = 2)
3 2 6 2 2 A tie: drop 7 (R = 5)
4 2 5 2 1 Drop 3 (L = 3)
5 3 5 - - 3 values = k: stop

Result: [4, 5, 6]

Edge Cases

  • x left of every value: the right end is always farther, so the answer is the first k values.
  • x right of every value: the answer is the last k values.
  • k = n: the loop never runs and the whole array is returned.
  • Ties: drop R. The comparison that drops L must be a strict >, or a tie would throw away the smaller value.
  • Duplicates: equal values have equal distances, and the same tie rule applies.

Solution

The shrinking window, O(n) time and O(1) extra space — the same method in every language.

Find K Closest Elements Code
1/**
2 * @param {number[]} arr
3 * @param {number} k
4 * @param {number} x
5 * @return {number[]}
6 */
7var findClosestElements = function(arr, k, x) {
8 let L = 0;
9 let R = arr.length - 1;
10
11 while (R - L + 1 > k) {
12 if (Math.abs(arr[L] - x) > Math.abs(arr[R] - x)) {
13 L++;
14 } else {
15 R--;
16 }
17 }
18
19 return arr.slice(L, R + 1);
20};

The approach, step by step

  1. Start wide

    Let the window [L, R] be the whole array.

  2. Drop the farther end

    While it holds more than k values, drop L if arr[L] is strictly farther from x than arr[R]; otherwise drop R.

  3. Return the window

    Return arr[L..R], the k closest values in ascending order.

Frequently asked questions

Why not use a heap for Find K Closest Elements?

A max-heap of size k works in O(n log k) on any array, but this array is sorted, so the answer is one contiguous run. Shrinking a window from its farther end finds it in O(n) with O(1) extra space.


How are ties handled?

When arr[L] and arr[R] are equally far from x, the smaller value wins, and that is arr[L] — so the code drops R. That is why the comparison that drops L is a strict greater-than.


Is the result sorted?

Yes. The window is a slice of a sorted array, so arr[L..R] is already in ascending order.

Applying for software engineering roles? Free, no sign-up:

AI resume checker — match your resume to the job description