1.题目描述
给定一个 排序好 的数组 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 测试结果
通过测试
3.总结
- 使用 Info 类封装数组元素信息
- 使用 Info 类型的优先级队列存放每个数字,并重写比较方法,如果差值相同比较索引;差值不同比较差值