返回

LeetCode:找到 K 个最接近的元素

后端

算法

本题可以使用二分查找算法来解决。具体步骤如下:

  1. 使用二分查找算法找到数组中第一个大于或等于 x 的元素的下标 i。
  2. 初始化一个长度为 k 的结果数组 result。
  3. 将 result[0] 设为 arr[i]。
  4. 将 result[1] 设为 arr[i-1],如果 i > 0。
  5. 将 result[2] 设为 arr[i+1],如果 i < arr.length - 1。
  6. 使用 while 循环来填充 result 数组的剩余元素。
  7. 在循环中,比较 result[0] 和 result[k-1] 与 x 的距离。
  8. 如果 result[0] 与 x 的距离更大,则将 result[0] 删除,并将 arr[i-1] 添加到 result 的开头。
  9. 如果 result[k-1] 与 x 的距离更大,则将 result[k-1] 删除,并将 arr[i+1] 添加到 result 的结尾。
  10. 重复步骤 7 和 8,直到 result 数组中包含 k 个元素。

代码

import java.util.Arrays;

class Solution {
    /**
     * 给定一个 排序好 的数组 arr ,两个整数 k 和 x ,从数组中找到最靠近 x(两数之差最
     * 小)的 k 个元素,并返回这 k 个元素。
     * 如果存在多个距离相等的元素,则返回按原数组顺序排列的这些元素。
     *
     * @param arr 已排序数组
     * @param k   要找的最接近元素的数量
     * @param x   目标元素
     * @return 最接近 x 的 k 个元素
     */
    public int[] findClosestElements(int[] arr, int k, int x) {
        int n = arr.length;
        int left = 0;
        int right = n - 1;

        while (left < right) {
            int mid = left + (right - left) / 2;
            if (arr[mid] == x) {
                return Arrays.copyOfRange(arr, Math.max(0, mid - k / 2), Math.min(n, mid + k / 2 + 1));
            } else if (arr[mid] < x) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }

        int[] result = new int[k];
        result[0] = arr[left];
        int i = 1;
        int j = left - 1;
        int m = left + 1;

        while (i < k) {
            if (j >= 0 && (x - arr[j] <= arr[m] - x)) {
                result[i++] = arr[j--];
            } else {
                result[i++] = arr[m++];
            }
        }

        return result;
    }
}

复杂度分析

  • 时间复杂度:O(log n + k),其中 n 是数组 arr 的长度。
  • 空间复杂度:O(k),其中 k 是要找的最接近元素的数量。

结语

本题考察二分查找算法的使用以及如何处理数组中存在多个距离相等的元素的情况。