Talentd
FleetCode
Make and follow sheets.Sign in

Find K Closest Elements solution and explanation

MediumArrayBinary SearchHeap (Priority Queue)Sliding Window5 min read50.1% acceptanceUpdated 9 Apr 2026
Find K Closest Elements - Leetcode 658 - PythonNeetCode · 18:21 · 116K viewsWatch on YouTube
9 more videos on this problem
  1. Find K Closest Elements - Leetcode 658 - PythonNeetCode · 18:21 · 116K views
  2. Find K Closest Elements | LeetCode 658 | Coders CampCoders Camp · 10:40 · 12K views
  3. 658. Find k closest elements | Leetcode | Medium | Java | Binary Search | Two PointersAlgorithmHQ · 11:42 · 6K views
  4. Coding Interview: Find K Closest ElementsJames Cutajar · 19:14 · 5K views
  5. [Java] Leetcode 658. Find K Closest Elements [Binary Search #8]Eric Programming · 15:06 · 5K views
  6. LeetCode 658. Find K Closest ElementsHappy Coding · 10:09 · 4K views
  7. Leetcode 658: Find K Closest Elements | Binary Search | Intuition and ApproachCode Concepts with Animesh · 33:27 · 2K views
  8. LeetCode 658. Find K Closest Elements | JSer - JavaScript & AlgorithmJSer · 18:44 · 1K views
  9. Coding Interview Problem - Find K Closest ElementsKnapsack · 7:18 · 1K views
  10. LeetCode 658: Find K Closest Elements: Python MediumHashem Alsaket · 6:29 · 1K views

The problem

Given a sorted integer array arr, two integers k and x, return the k closest integers to x in the array. The result should also be sorted in ascending order.

An integer a is closer to x than an integer b if:

  • |a - x| < |b - x|, or
  • |a - x| == |b - x| and a < b

Example 1:

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

Output: [1,2,3,4]

Example 2:

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

Output: [1,1,2,3]

Constraints:

  • 1 <= k <= arr.length
  • 1 <= arr.length <= 104
  • arr is sorted in ascending order.
  • -104 <= arr[i], x <= 104

Approach overview

Problem Overview: Given a sorted array arr, an integer k, and a target x, return the k elements closest to x. If two numbers are equally close, the smaller value is preferred. The result must also remain sorted.

Approach 1: Two Pointers Shrinking Window (O(n) time, O(1) space)

This method keeps a window covering the entire array and repeatedly removes the element that is farther from x. Start with two pointers: left = 0 and right = n - 1. While the window size is larger than k, compare |arr[left] - x| and |arr[right] - x|. Remove the element with the larger distance by moving the corresponding pointer inward. Because the array is already sorted, the remaining window of size k is guaranteed to contain the closest elements. This approach uses the Two Pointers technique and works well when simplicity matters more than optimal logarithmic performance.

Approach 2: Binary Search with Sliding Window (O(log(n-k)) + O(k) time, O(1) space)

The array is sorted, which allows you to binary search the starting index of the optimal window of size k. Instead of searching for a single element, search the range [0, n-k]. For a candidate start mid, compare x - arr[mid] with arr[mid + k] - x. If the left side is larger, the window should move right; otherwise it should stay left. This works because the relative distances determine which side of the window is farther from x. After binary search finishes, the subarray arr[left : left + k] contains the answer. The window behaves like a fixed-size Sliding Window while binary search narrows the correct position using the properties of a sorted Binary Search space.

Recommended for interviews: Binary Search with Sliding Window is the expected optimal solution. It reduces the search space to log(n-k) comparisons and avoids scanning the whole array. Interviewers often accept the two-pointer shrinking approach first because it shows understanding of distance comparison, but the binary search optimization demonstrates stronger algorithmic reasoning on sorted arrays.

Approach 1: Binary Search with Sliding Window

This approach uses binary search to find the position where x would fit in the array or where it is located. From this point, a sliding window is expanded to the left and right to check k closest elements. Given the sorted nature of the array, this is efficient.

def find_closest_elements(arr, k, x):
    left, right = 0, len(arr) - k
    while left < right:
        mid = (left + right) // 2
        if x - arr[mid] > arr[mid + k] - x:
            left = mid + 1
        else:
            right = mid
    return arr[left:left + k]
import java.util.*;

class Solution {
    public List<Integer> findClosestElements(int[] arr, int k, int x) {
        int left = 0, right = arr.length - k;
        while (left < right) {
            int mid = (left + right) / 2;
            if (x - arr[mid] > arr[mid + k] - x)
                left = mid + 1;
            else
                right = mid;
        }
        List<Integer> result = new ArrayList<>();
        for (int i = left; i < left + k; ++i) {
            result.add(arr[i]);
        }
        return result;
    }
}
#include <vector>
#include <algorithm>
using namespace std;

vector<int> findClosestElements(vector<int>& arr, int k, int x) {
    int left = 0, right = arr.size() - k;
    while (left < right) {
        int mid = (left + right) / 2;
        if (x - arr[mid] > arr[mid + k] - x)
            left = mid + 1;
        else
            right = mid;
    }
    return vector<int>(arr.begin() + left, arr.begin() + left + k);
}
function findClosestElements(arr, k, x) {
    let left = 0, right = arr.length - k;
    while (left < right) {
        const mid = Math.floor((left + right) / 2);
        if (x - arr[mid] > arr[mid + k] - x)
            left = mid + 1;
        else
            right = mid;
    }
    return arr.slice(left, left + k);
}
#include <stdlib.h>

void merge(int* arr, int* aux, int left, int mid, int right) {
    int i = left, j = mid + 1, k = left;
    while (i <= mid && j <= right) {
        if (abs(arr[i]) <= abs(arr[j]))
            aux[k++] = arr[i++];
        else
            aux[k++] = arr[j++];
    }
    while (i <= mid) aux[k++] = arr[i++];
    while (j <= right) aux[k++] = arr[j++];
    for (i = left; i <= right; i++) arr[i] = aux[i];
}

void mergesort(int* arr, int* aux, int left, int right) {
    if (left < right) {
        int mid = left + (right - left) / 2;
        mergesort(arr, aux, left, mid);
        mergesort(arr, aux, mid + 1, right);
        merge(arr, aux, left, mid, right);
    }
}

int* findKClosestElements(int* arr, int arrSize, int k, int x, int* returnSize) {
    int *aux = (int*)malloc(arrSize * sizeof(int));
    for (int i = 0; i < arrSize; ++i)
        arr[i] -= x;
    mergesort(arr, aux, 0, arrSize - 1);
    for (int i = 0; i < arrSize; ++i)
        arr[i] += x;
    *returnSize = k;
    free(aux);
    return arr;
}
using System;
using System.Collections.Generic;

public class Solution {
    public IList<int> FindClosestElements(int[] arr, int k, int x) {
        int left = 0, right = arr.Length - k;
        while (left < right) {
            int mid = (left + right) / 2;
            if (x - arr[mid] > arr[mid + k] - x) 
                left = mid + 1;
            else
                right = mid;
        }
        List<int> result = new List<int>();
        for (int i = left; i < left + k; ++i) {
            result.Add(arr[i]);
        }
        return result;
    }
}

We initiate a binary search between 0 and len(arr) - k. Depending on whether the element x is closer to the left or right side, we move the binary search mid-point. Once the position is found, the array is sliced from left to left + k to get the result.

Complexity

Time Complexity: O(log(n-k) + k) where n is the length of the array, and we are moving a window over it. Space Complexity: O(k) for storing the resulting subarray.

Try this approach in the editor

Approach 2: Two Pointers

This approach initiates two pointers from the start and end of the array and gradually closes inwards by comparing the distance from x from both ends until the closest k elements are left. This is linear after the search initialization.

def find_closest_elements(arr, k, x):
    left, right = 0, len(arr) - 1
    while right - left >= k:
        if abs(arr[left] - x) > abs(arr[right] - x):
            left += 1
        else:
            right -= 1
    return arr[left:right + 1]
import java.util.*;

class Solution {
    public List<Integer> findClosestElements(int[] arr, int k, int x) {
        int left = 0, right = arr.length - 1;
        while (right - left >= k) {
            if (Math.abs(arr[left] - x) > Math.abs(arr[right] - x))
                left++;
            else
                right--;
        }
        List<Integer> result = new ArrayList<>();
        for (int i = left; i <= right; ++i) {
            result.add(arr[i]);
        }
        return result;
    }
}
#include <vector>
#include <cstdlib> // for abs
using namespace std;

vector<int> findClosestElements(vector<int>& arr, int k, int x) {
    int left = 0, right = arr.size() - 1;
    while (right - left >= k) {
        if (abs(arr[left] - x) > abs(arr[right] - x))
            left++;
        else
            right--;
    }
    return vector<int>(arr.begin() + left, arr.begin() + right + 1);
}
function findClosestElements(arr, k, x) {
    let left = 0, right = arr.length - 1;
    while (right - left >= k) {
        if (Math.abs(arr[left] - x) > Math.abs(arr[right] - x))
            left++;
        else
            right--;
    }
    return arr.slice(left, right + 1);
}
#include <stdlib.h>

int cmp(const void *a, const void *b) {
    return abs(*(int*)a - x) - abs(*(int*)b - x);
}

int* findClosestElements(int* arr, int arrSize, int k, int x, int* returnSize) {
    qsort(arr, arrSize, sizeof(int), cmp);
    qsort(arr, k, sizeof(int), cmp);
    *returnSize = k;
    return arr;
}
using System;
using System.Collections.Generic;

public class Solution {
    public IList<int> FindClosestElements(int[] arr, int k, int x) {
        int left = 0, right = arr.Length - 1;
        while (right - left >= k) {
            if (Math.Abs(arr[left] - x) > Math.Abs(arr[right] - x))
                left++;
            else
                right--;
        }
        List<int> result = new List<int>();
        for (int i = left; i <= right; ++i)
            result.Add(arr[i]);
        return result;
    }
}

Using two pointers from both ends of the array, we check which value is closer to x and move the respective pointer inwards until only k elements are left. These k elements will be the closest to x.

Complexity

Time Complexity: O(n). Space Complexity: O(k).

Try this approach in the editor

Approach 3: Sort

function findClosestElements(arr: number[], k: number, x: number): number[] {
    let l = 0;
    let r = arr.length;
    while (r - l > k) {
        if (x - arr[l] <= arr[r - 1] - x) {
            --r;
        } else {
            ++l;
        }
    }
    return arr.slice(l, r);
}
func findClosestElements(arr []int, k int, x int) []int {
	sort.Slice(arr, func(i, j int) bool {
		v := abs(arr[i]-x) - abs(arr[j]-x)
		if v == 0 {
			return arr[i] < arr[j]
		}
		return v < 0
	})
	ans := arr[:k]
	sort.Ints(ans)
	return ans
}

func abs(x int) int {
	if x >= 0 {
		return x
	}
	return -x
}
impl Solution {
    pub fn find_closest_elements(arr: Vec<i32>, k: i32, x: i32) -> Vec<i32> {
        let n = arr.len();
        let mut l = 0;
        let mut r = n;
        while r - l != (k as usize) {
            if x - arr[l] <= arr[r - 1] - x {
                r -= 1;
            } else {
                l += 1;
            }
        }
        arr[l..r].to_vec()
    }
}
Try this approach in the editor

Approach 4: Binary search

function findClosestElements(arr: number[], k: number, x: number): number[] {
    let left = 0;
    let right = arr.length - k;
    while (left < right) {
        const mid = (left + right) >> 1;
        if (x - arr[mid] <= arr[mid + k] - x) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }
    return arr.slice(left, left + k);
}
func findClosestElements(arr []int, k int, x int) []int {
	l, r := 0, len(arr)
	for r-l > k {
		if x-arr[l] <= arr[r-1]-x {
			r--
		} else {
			l++
		}
	}
	return arr[l:r]
}
impl Solution {
    pub fn find_closest_elements(arr: Vec<i32>, k: i32, x: i32) -> Vec<i32> {
        let k = k as usize;
        let n = arr.len();
        let mut left = 0;
        let mut right = n - k;
        while left < right {
            let mid = left + (right - left) / 2;
            if x - arr[mid] > arr[mid + k] - x {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        arr[left..left + k].to_vec()
    }
}
Try this approach in the editor

Approach 5: Default Approach

func findClosestElements(arr []int, k int, x int) []int {
	left, right := 0, len(arr)-k
	for left < right {
		mid := (left + right) >> 1
		if x-arr[mid] <= arr[mid+k]-x {
			right = mid
		} else {
			left = mid + 1
		}
	}
	return arr[left : left+k]
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Binary Search with Sliding Window

Time Complexity: O(log(n-k) + k) where n is the length of the array, and we are moving a window over it. Space Complexity: O(k) for storing the resulting subarray.

Two Pointers

Time Complexity: O(n). Space Complexity: O(k).

Sort–
Binary search–
Default Approach–

Complexity analysis

ApproachTimeSpaceWhen to Use
Two Pointers Shrinking WindowO(n)O(1)When the array is sorted and you want a straightforward implementation without binary search
Binary Search + Sliding WindowO(log(n-k)) + O(k)O(1)Best choice for large arrays where you want the optimal logarithmic search

Frequently asked questions

Is Find K Closest Elements easy or hard?

Find K Closest Elements is considered a Medium difficulty problem. The two-pointer approach is relatively straightforward, but identifying the binary search window optimization requires stronger understanding of sorted array properties.

Find K Closest Elements Python or Java solution?

The logic is identical across languages. Implement binary search to find the left boundary of the window, then return the next k elements. Python typically slices the array, while Java and C++ return a sublist or iterate to build the result.

How to solve Find K Closest Elements in O(log n)?

Use binary search to find the starting index of the k-length window that minimizes the distance to x. Search between indices 0 and n-k and compare x - arr[mid] with arr[mid + k] - x to decide which direction to move. After the search, return the subarray from start to start + k.

What is the best approach for Find K Closest Elements?

Binary Search with a fixed-size sliding window is the most efficient approach. Instead of checking every element, it binary searches the starting index of a window of size k in the sorted array. The algorithm runs in O(log(n-k)) time plus O(k) to return the result, making it faster than scanning the entire array.

What data structure is used in Find K Closest Elements?

The core solutions rely mainly on arrays combined with algorithmic techniques like binary search and two pointers. Some alternative implementations also use a heap (priority queue) to track closest elements, but the optimal interview solution avoids extra data structures.

What is the time complexity of Find K Closest Elements?

The optimal solution runs in O(log(n-k)) time using binary search to locate the best window of size k. Returning the k elements adds O(k) time. A simpler two-pointer shrinking window approach runs in O(n) time because it repeatedly removes elements from the edges.

Is Find K Closest Elements asked at Google, Amazon, or Meta?

Find K Closest Elements frequently appears in coding interviews at large tech companies including Amazon, Google, and Meta. The problem tests understanding of binary search on answer space, sliding window reasoning, and handling edge cases in sorted arrays.

Comments

Now write it yourselfClose this page and solve Find K Closest Elements in the editor, without looking.
Practise Find K Closest Elements