LeetCode 每日一题——658. 找到 K 个最接近的元素

258 阅读1分钟

1.题目描述

658. 找到 K 个最接近的元素

给定一个 排序好 的数组 arr ,两个整数 k 和 x ,从数组中找到最靠近 x(两数之差最小)的 k 个数。返回的结果必须要是按升序排好的。

整数 a 比整数 b 更接近 x 需要满足:

|a - x| < |b - x| 或者 |a - x| == |b - x| 且 a < b  

示例 1:

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

示例 2:

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

 

2.解题思路与代码

2.1 解题思路

这道题需要找到有序数组数组中最接近 x 的 k 个数,并且尽量让这 k 个数小。那么既然要求接近 x 的数,就比绕需要比较数组中的书与 x 差的绝对值,在计算到差值后便可以按照差值大小求出前 k 个小的元素,那么这里我们就可以想到使用堆来完成。题目还有一个需求便是尽量让取数组中尽可能小的元素,因为差值使用绝对值那么我们就需要考虑到如果差值相同时,让数值更小的那一个在前面。我们使用一个 Info 类封装数组中各个数字、数字与 x 的差值以及数字所在数组的索引。然后构建一个 Info 类泛型优先级队列,并重新队列的比较方法,如果差值相同比较索引;如果差值不同,比较差值即可。 数组全部进入优先级队列之后再从队列中弹出前 k 个元素放入结果列表中即可,由于比较差值是绝对值,因此从队列中出来的元素可能存在值大的在队列前面,因此最后对结果列表进行排序返回即可。

2.2 代码

class Solution {
    public List<Integer> findClosestElements(int[] arr, int k, int x) {
        PriorityQueue<Info> queue = new PriorityQueue<>((o1, o2) -> {
            if (o1.diff - o2.diff == 0) {
                return o1.index - o2.index;
            } else {
                return o1.diff - o2.diff;
            }
        });
        for (int i = 0; i < arr.length; i++) {
            queue.offer(new Info(arr[i], Math.abs(arr[i] - x), i));
        }
        List<Integer> ans = new ArrayList<>();
        for (int i = 0; i < k; i++) {
            ans.add(queue.poll().num);
        }
        ans.sort(Comparator.comparingInt(o -> o));
        return ans;
    }

    static class Info {
        int num;
        int diff;
        int index;

        public Info(int num, int diff, int index) {
            this.num = num;
            this.diff = diff;
            this.index = index;
        }
    }
}

2.3 测试结果

通过测试

image.png

3.总结

  • 使用 Info 类封装数组元素信息
  • 使用 Info 类型的优先级队列存放每个数字,并重写比较方法,如果差值相同比较索引;差值不同比较差值