---
# System prepended metadata

title: '[LeetCode 658. Find K Closest Elements ]()'

---

# [LeetCode 658. Find K Closest Elements ]()
### Daily challenge Jul 17, 2021 (EASY)

>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`


:::info
**Example 1:**
**Input:** arr = [1,2,3,4,5], k = 4, x = 3
**Output:** [1,2,3,4]
:::

:::info
**Example 2:**
**Input:** arr = [1,2,3,4,5], k = 4, x = -1
**Output:** [1,2,3,4]
:::

:::warning
**Constraints:**
* 1 <= k <= arr.length
* 1 <= arr.length <= 104
* arr is sorted in ascending order.
* -104 <= arr[i], x <= 104
:::

---



### Approach 1 : Binary Search :bulb: 
**`40 ms ( 65.40% )`** **`O()`**

利用 `Bianary Search` 找到 **`x`** 在 `arr` 中最靠近的位置 ( `x` 可能不存在 `arr` 中)。

找到後利用兩個 `pointer ( left & right )`，判斷何者較接近 `x`，並存入 `vector` 中，最後進行 `sort` 後回傳。


```cpp=1
class Solution {
public:
    vector<int> findClosestElements(vector<int>& arr, int k, int x) {
        vector<int > ans;
        
        bool flag = false;
        int left = 0;
        int right = arr.size()-1;
        int middle = 0;
        
        // find index of value of x
        while(left <= right){
            cout << left << " " << right << endl;
            middle = (left + right) / 2;
            
            if(arr[middle] == x){
                flag = true;
                break;
            }
            else if(arr[middle] < x)    left = middle + 1;
            else    right = middle - 1;
        }
        
        // use two pointer to check which element is closer to x
        if(!flag){
            int t = left;
            left = right;
            right = t;
        }
        else{
            left = middle - 1;
            right = middle;
        }
        
        while(ans.size() != k){
            // when x is in the begin or end
            if(left < 0){
                for(int i=right; ans.size() != k; i++){
                    ans.push_back(arr[i]);
                }   
                break;
            }
            else if(right >=arr.size()){
                for(int i=left; ans.size() != k; i--){
                    ans.push_back(arr[i]);
                }
                break;
            }
            
            // between
            if( x - arr[left] <= arr[right] - x){
                ans.push_back(arr[left]);
                left--;
            }
            else{
                ans.push_back(arr[right]);
                right++;
            }
        }
        
        sort(ans.begin(), ans.end());
        return ans;
    }
};
```

### Approach 2 : Two Pointer :book: 
**`36 ms ( 81.07% )`** **`O(N)`**

使用兩個 `pointer ( left & right )`，判斷 **`abs(arr[left] - x)、abs(arr[right] - x)`** 兩者的大小。

```cpp=1
class Solution {
public:
    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);
    }
};
```

### Approach 3 : Binary Search :book: 
**`36 ms ( 81.07% )`** **`O(log(N - K))`**

:::danger
**`x - arr[mid]`** and **`arr[mid + k] - x`**，判斷時不能使用 abs()，結果會錯誤。
:::

>Assume we are taking **`A[left] ~ A[left + k -1]`**.
We can binary research `i`.
We compare the distance between `x - A[mid]` and `A[mid + k] - x`.
>
>* case 1: x - A[mid] < A[mid + k] - x, need to move window go `left`
-------**x**----A[mid]-----------------A[mid + k]----------
>* case 2: x - A[mid] < A[mid + k] - x, need to move window go `left`
-------A[mid]----**x**-----------------A[mid + k]----------
>* case 3: x - A[mid] > A[mid + k] - x, need to move window go `right`
-------A[mid]------------------**x**---A[mid + k]----------
>* case 4: x - A[mid] > A[mid + k] - x, need to move window go `right`
-------A[mid]---------------------A[mid + k]----**x**------
>
>`If x - A[mid] > A[mid + k] - x`,
it `means A[mid + 1] ~ A[mid + k]` is better than `A[mid] ~ A[mid + k - 1]`,
and we have mid `smaller` than the right `i`.
So assign `left = mid + 1`.

```cpp=1
class Solution {
public:
    vector<int> findClosestElements(vector<int>& arr, int k, int x) {
        int left = 0;
        int right = arr.size() - k;
        
        while(left < right){
            int middle = (left + right) / 2;
            
            if(x - arr[middle] > arr[middle + k] - x){
                left = middle + 1;
            }
            else{
                right = middle;
            }
        }
        
        return vector<int > (arr.begin() + left, arr.begin() + left + k);
    }
};
```