Solved·14 Sept
Find K Closest Elements
DifficultyMedium
PatternBinary Search
TrackDSA
tl;dr
You are given a sorted array of integers, nums, and two integers, target and k. Your task is to return k integers from nums that are the closest to target. The integers in the output should be in sorted order.
full write-up
Find K Closest Elements
Problem Statement
You are given a sorted array of integers, nums, and two integers, target and k. Your task is to return k integers from nums that are the closest to target. The integers in the output should be in sorted order.
An integer nums[i] is considered closer to target than nums[j] when:
|nums[i] - target| < |nums[j] - target|
However, if both distances are equal (|nums[i] - target| == |nums[j] - target|), the smaller of the two values is chosen.
Constraints
1 ≤ k ≤ nums.length1 ≤ nums.length ≤ 10³numsis sorted in ascending order.−10⁴ ≤ nums[i], target ≤ 10⁴
Solution
Since nums is already sorted, we can start by finding the element closest to target, and then build a window of size k around it.
Steps
- First, we handle a few simple cases directly:
- If the array's length already equals
k, we just return the whole array. - If
targetis less than or equal to the first element, the closestkelements are simply the firstkelements of the array. - If
targetis greater than or equal to the last element, the closestkelements are the lastkelements of the array.
- If the array's length already equals
- Otherwise, we find the position of the element closest to
targetusing binary search. This gives us a starting point. - We then set up a small window, just one step wide at first, right around this closest position.
- We grow the window one step at a time, until it reaches size
k:- We compare the element just outside the window on the left with the element just outside the window on the right.
- Whichever one is closer to
target(or equally close but smaller), we bring it into the window. - If the left side has run out of elements (
windowLeft === -1), we can only expand to the right. - If the right side has run out of elements, we can only expand to the left.
- Once the window reaches size
k, we return the elements inside it.
Code
function findClosestElements(nums, k, target) {
if (nums.length === k) {
return nums;
}
if (target <= nums[0]) {
return nums.slice(0, k);
}
if (target >= nums[nums.length - 1]) {
return nums.slice(nums.length - k);
}
const firstClosest = binarySearch(nums, target);
let windowLeft = firstClosest - 1;
let windowRight = windowLeft + 1;
while (windowRight - windowLeft - 1 < k) {
if (windowLeft === -1) {
windowRight++;
continue;
}
if (windowRight === nums.length || Math.abs(nums[windowLeft] - target) <= Math.abs(nums[windowRight] - target)) {
windowLeft--;
}
else {
windowRight++;
}
}
return nums.slice(windowLeft + 1, windowRight);
}