# [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); } }; ```