###### Heap

# Find K Closest Elements

### Description (inspired by [Leetcode.com](https://leetcode.com/problems/find-k-closest-elements))
Given a sorted array nums, a target value target, and an integer k, find the k closest elements to target in the array, where "closest" is the absolute difference between each element and target. Return these elements in array, sorted in ascending order.

**Example 1:**

Inputs:

```
nums = [-1, 0, 1, 4, 6]
target = 1
k = 3
```

Output:

```
[-1, 0, 1]
```

**Explanation:** -1 is 2 away from 1, 0 is 1 away from 1, and 1 is 0 away from 1. All other elements are more than 2 away. Since we need to return the elements in ascending order, the answer is 
[-1, 0, 1]

**Example 2:**

Inputs:

```
nums = [5, 6, 7, 8, 9]
target = 10
k = 2
```

Output:

```
[8, 9]
```

### 💻 Desktop Required
The code editor works best on larger screens.

### Explanation

#### Approach 1: Sorting
The simplest approach is to calculate the distance of each element from the target and to sort the elements based on that distance. This approach has a time complexity of O(n log n) where n is the number of points in the array, and a space complexity of O(n) (to store the sorted array of distances).

#### Approach 2: Max-Heap
This problem can be solved using a similar approach to the one used to solve [Kth Largest Element in an Array](/content/learn/code/heap/kth-largest-element-in-an-array/index.html), with the key difference being that we need to find the _k closest elements_ to the target, rather than the _k largest elements_. Since we are looking for the k smallest elements, we need a **max-heap**, rather than a min-heap.

By default, python's heapq module implements a min-heap, but we can make it behave like a max-heap by negating the values of everything we push onto it.

First, we push the first k elements to the heap by storing a tuple containing the _negative of the distance_ of the element from the target, and the element itself. After that is finished, our heap contains the k closest elements to the target that we've seen so far, with the element furthest from the target at the root of the heap.

```python

def k_closest(nums, k, target):
    heap = []
    for num in nums:
        distance = abs(num - target)
        if len(heap) < k:
            heapq.heappush(heap, (-distance, num))
        elif distance < -heap[0][0]:
            heapq.heappushpop(heap, (-distance, num))

distances = [pair[1] for pair in heap]
    distances.sort()
    return distances
```

### Complexity Analysis
**Time Complexity:** O(n * log k) where `n` is the number of elements in the array and `k` is the number of closest elements to find. We iterate over all the elements in the array. At each iteration, comparing the current element with the root of the heap takes O(1) time. In the worst case, we both `push` and `pop` each element from the heap, which takes O(log k) time.

**Space Complexity:** O(k) where `k` is the number of closest elements to find. The space used by the heap to store the `k` closest elements to the target.

### Bonus Approach: Two Pointers + Binary Search
We can also leverage the fact that the input array is sorted to solve this problem using a two-pointer approach combined with binary search. This approach is based on the observation that the k closest elements to the target will occur in a contiguous subarray of length k in the sorted array.

```python

def findClosestElements(nums, k, target):
    left, right = 0, len(nums) - k
    while left < right:
        mid = left + (right - left) // 2
        if target - nums[mid] > nums[mid + k] - target:
            left = mid + 1
        else:
            right = mid
    return nums[left:left + k]
```
