leetcode 658.找到K個最接近的元素 Java

雲水冰發表於2020-11-14

題目連結

https://leetcode-cn.com/problems/find-k-closest-elements/

描述

給定一個排序好的陣列,兩個整數 k 和 x,從陣列中找到最靠近 x(兩數之差最小)的 k 個數。返回的結果必須要是按升序排好的。如果有兩個數與 x 的差值一樣,優先選擇數值較小的那個數。

說明:

k 的值為正數,且總是小於給定排序陣列的長度。
陣列不為空,且長度不超過 104
陣列裡的每個元素與 x 的絕對值不超過 104
 

更新(2017/9/19):
這個引數 arr 已經被改變為一個整數陣列(而不是整數列表)。 請重新載入程式碼定義以獲取最新更改。

示例

示例 1:

輸入: [1,2,3,4,5], k=4, x=3
輸出: [1,2,3,4]

示例 2:

輸入: [1,2,3,4,5], k=4, x=-1
輸出: [1,2,3,4]

初始程式碼模板

class Solution {
    public List<Integer> findClosestElements(int[] arr, int k, int x) {

    }
}

程式碼

這個題目,相當棒!
寫了半天,也就擊敗50%,一開始是用二分查詢確定元素位置,然後再用雙指標新增元素。
以下是我寫的,效率並不是很高,建議直接看第二個,我是為了給自己漲個記性。

class Solution {
    public List<Integer> findClosestElements(int[] arr, int k, int x) {
        int xIndex = binarySearch(arr, x);

        LinkedList<Integer> ans = new LinkedList<>();
        int left = xIndex - 1;
        int right = xIndex;
        while (ans.size() < k) {
            int disLeft = left >= 0 ? x - arr[left] : Integer.MAX_VALUE;
            int disRight = right < arr.length ? arr[right] - x : Integer.MAX_VALUE;

            if (disLeft <= disRight) {
                ans.addFirst(arr[left]);
                left--;
            } else {
                ans.add(arr[right]);
                right++;
            }
        }
        
        return ans;
    }

    private int binarySearch(int[] arr, int target) {
        int left = 0;
        int right = arr.length - 1;
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (arr[mid] == target) {
                right = mid;
            } else if (arr[mid] < target) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }

        return left;
    }
}

下面這個是大佬寫的,可以去看看解析,寫的太棒了:
https://leetcode-cn.com/problems/find-k-closest-elements/solution/pai-chu-fa-shuang-zhi-zhen-er-fen-fa-python-dai-ma/

public class Solution {

    public List<Integer> findClosestElements(int[] arr, int k, int x) {
        int size = arr.length;

        int left = 0;
        int right = size - k;

        while (left < right) {
            // int mid = left + (right - left) / 2;
            int mid = (left + right) >>> 1;
            // 嘗試從長度為 k + 1 的連續子區間刪除一個元素 
            // 從而定位左區間端點的邊界值
            if (x - arr[mid] > arr[mid + k] - x) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }

        List<Integer> res = new ArrayList<>();
        for (int i = left; i < left + k; i++) {
            res.add(arr[i]);
        }
        return res;
    }
}

相關文章