❗❗❗必看:
下列题我全部都使用 Java 语言写的,并且均可以提交成功,获得Accepted 结果的. 如果代码和详解看了之后,对答案有任何疑问,都可以在评论区提出来,我都会一个一个回答.
❗❗❗感谢大家的支持,如果喜欢我的博客,关注 点赞 收藏 评论一波,非常感谢!!!
题目:查找最接近的元素
在一个非降序列中,查找与给定值最接近的元素。
Input
第一行包含一个整数n,为非降序列长度。1 <= n <= 100000。
第二行包含n个整数,为非降序列各元素。所有元素的大小均在0-1,000,000,000之间。
第三行包含一个整数m,为要询问的给定值个数。1 <= m <= 10000。
接下来m行,每行一个整数,为要询问最接近元素的给定值。所有给定值的大小均在0-1,000,000,000之间。
Output
m行,每行一个整数,为最接近相应给定值的元素值,保持输入顺序。若有多个值满足条件,输出最小的一个。
样例测试
输入
3
2 5 8
2
10
5
输出
8
5
代码
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 读取非降序列长度
int n = sc.nextInt();
int[] arr = new int[n];
// 读取非降序列
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
// 读取查询个数
int m = sc.nextInt();
int[] queries = new int[m];
// 读取每个查询值
for (int i = 0; i < m; i++) {
queries[i] = sc.nextInt();
}
// 使用StringBuilder减少I/O操作次数
StringBuilder sb = new StringBuilder();
// 处理每个查询并输出结果
for (int i = 0; i < m; i++) {
sb.append(findClosest(arr, queries[i])).append("\n");
}
// 输出所有结果
System.out.print(sb.toString());
sc.close();
}
public static int findClosest(int[] arr, int target) {
int pos = Arrays.binarySearch(arr, target);
if (pos >= 0) {
// 目标值在数组中,直接返回
return arr[pos];
} else {
// 目标值不在数组中,计算插入点
int insertionPoint = -pos - 1;
if (insertionPoint == 0) {
// 插入点在数组起始位置,返回第一个元素
return arr[0];
} else if (insertionPoint == arr.length) {
// 插入点在数组末尾,返回最后一个元素
return arr[arr.length - 1];
} else {
// 插入点在数组中间,比较前后元素
int before = arr[insertionPoint - 1];
int after = arr[insertionPoint];
if (Math.abs(before - target) <= Math.abs(after - target)) {
return before;
} else {
return after;
}
}
}
}
}
初步思路
利用二分查找快速定位目标值在非降序列中的位置,找到最接近的元素。
具体步骤
-
读取输入:
- 首先读取非降序列的长度 n。
- 然后读取非降序列的 n 个元素。
- 接着读取查询的个数 m。
- 最后读取 m 个查询值。
-
使用二分查找:
- 对于每个查询值 target,使用 Arrays.binarySearch(arr, target) 在非降序列中进行二分查找。
-
处理二分查找结果:
- 如果找到目标值,直接返回该值。
- 如果未找到,Arrays.binarySearch 返回负的插入点位置 -pos-1。
- 根据插入点位置确定最接近的元素:
- 如果插入点位置为 0,返回数组的第一个元素。
- 如果插入点位置在数组末尾,返回数组的最后一个元素。
- 否则,比较插入点前后的两个元素,返回距离目标值较近的元素(若距离相同,返回较小的元素)。
-
输出结果:
- 将每个查询的结果存入 StringBuilder 中,最后一次性输出所有结果以减少 I/O 操作。
总结方法
这个方法通过利用二分查找的特性高效定位目标值的位置,并根据插入点前后的元素进行比较,确保找到最接近的值。通过减少 I/O 操作,提高了整体的运行效率。这种方法在处理大规模数据时尤为有效,体现了算法优化的重要性。