mjhcsp 2025-10-27 19:45 采纳率: 100%
浏览 8
已结题

请人出数据吧!不会出

U622845 查找最接近的元素
提交答案加入题单复制题目编辑题目
提交
0
通过
0
时间限制

内存限制

题目编号
U622845
提供者
mjhcsp1
难度
普及−
历史分数
暂无
提交记录
标签
推荐题目
暂无
复制 Markdown
展开
进入 IDE 模式
题目背景
在一个非降序列中,查找与给定值最接近的元素。

题目描述
在一个非降序列中,查找与给定值最接近的元素。

输入格式
第一行包含一个整数n,为非降序列长度。1≤n≤10
6

第二行包含n个整数,为非降序列各元素。所有元素的大小均不超int。

第三行包含一个整数m,为要询问的给定值个数。1≤m≤10
4

接下来m行,每行一个整数,为要询问最接近元素的给定值。所有给定值的大小均1−10
9

输出格式
m行,每行一个整数,为最接近相应给定值的元素值,保持输入顺序。若有多个值满足条件,输出最小的一个。

输入输出样例
输入 #1复制

3
2 5 8
2
10
5
输出 #1复制
8
5
https://www.luogu.com.cn/problem/U622845

  • 写回答

3条回答 默认 最新

  • Juan_2012 2025-10-27 20:01
    关注

    回答参考qwen
    这是一个经典的二分查找问题:在非降序列中查找与给定值最接近的元素(即绝对值差最小),若有多个,返回最小的那个值。

    由于数据规模较大(n ≤ 10⁶, m ≤ 10⁴),必须使用 O(m log n) 的高效算法,不能暴力遍历每个查询。


    🎯【理解意图】

    用户需要解决一个编程题:在有序数组中对多个查询值快速找到“最接近”的元素。本质是二分定位 + 邻近比较

    技术背景推测:

    • 使用 C++ 编程
    • 要求正确处理边界情况(如查询值小于最小值或大于最大值)
    • 若有两个元素与目标距离相同,输出较小的那个

    🧠【成因剖析】

    常见错误原因包括:

    1. 直接线性扫描每个查询 → 时间复杂度 O(m×n),超时
    2. 二分写错边界条件 → 死循环或越界
    3. 未考虑左右邻接点比较 → 找到 lower_bound 但没比较前一个元素
    4. 相等距离时未取小值 → 违反“若有多个满足,输出最小”要求

    ✅【方案对比】

    方案一:使用 std::lower_bound 实现二分定位(推荐)

    实现步骤:
    1. 读入非降序列并存储为 vector
    2. 对每个查询值 x:
      • 使用 lower_bound 找第一个 ≥ x 的位置
      • 比较该位置和前一个位置的元素与 x 的距离
      • 返回距离更小者;距离相等时返回较小值
    核心代码示例(C++):
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <climits>
    using namespace std;
    
    int findClosest(const vector<int>& arr, int x) {
        int n = arr.size();
        auto it = lower_bound(arr.begin(), arr.end(), x);
        
        // 右侧元素(第一个 >= x)
        int right = (it != arr.end()) ? *it : INT_MAX;
        // 左侧元素(最后一个 < x)
        int left = (it != arr.begin()) ? *(it - 1) : INT_MIN;
    
        long long diffRight = (right == INT_MAX) ? LLONG_MAX : (long long)abs((long long)right - x);
        long long diffLeft = (left == INT_MIN) ? LLONG_MAX : (long long)abs((long long)left - x);
    
        if (diffLeft < diffRight) return left;
        else if (diffLeft > diffRight) return right;
        else return min(left, right);  // 相等距离取小值
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    
        int n;
        cin >> n;
        vector<int> arr(n);
        for (int i = 0; i < n; ++i) {
            cin >> arr[i];
        }
    
        int m;
        cin >> m;
        while (m--) {
            int x;
            cin >> x;
            cout << findClosest(arr, x) << '\n';
        }
    
        return 0;
    }
    
    ✅ 优点:
    • 时间复杂度 O(m log n),完全满足性能要求
    • 利用 STL 稳定可靠,不易出错
    • 边界清晰,易于维护
    ❌ 缺点:
    • 需要理解 lower_bound 含义
    • 注意防止越界访问(begin/end 判断)
    ✅ 适用场景:

    所有有序数组上的“最近邻”查询问题,尤其是多查询场景。


    方案二:手写二分查找

    实现思路:

    手动实现二分,找到插入位置后同样比较左右两个候选值。

    int binarySearchClosest(const vector<int>& arr, int x) {
        int left = 0, right = arr.size() - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (arr[mid] < x) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        // now 'left' is the first index where arr[left] >= x
        // compare arr[left] and arr[left-1]
        int candidate1 = (left > 0) ? arr[left - 1] : arr[0];
        int candidate2 = (left < arr.size()) ? arr[left] : arr.back();
    
        long long diff1 = abs((long long)candidate1 - x);
        long long diff2 = abs((long long)candidate2 - x);
    
        if (diff1 != diff2) return diff1 < diff2 ? candidate1 : candidate2;
        return min(candidate1, candidate2);
    }
    
    ✅ 优点:
    • 不依赖 STL,适合禁用库函数环境
    • 更加透明可控
    ❌ 缺点:
    • 容易写错边界(如 left=mid+1 写成 mid)
    • 调试成本高
    ✅ 适用场景:

    面试考察手撕代码能力、嵌入式系统等受限环境


    🏆【推荐决策】

    推荐使用方案一(std::lower_bound

    理由:

    • 开发效率高,代码简洁
    • 性能稳定,标准库高度优化
    • 在 OJ(在线评测系统)中广泛验证过可靠性
    • 更符合现代 C++ 工程实践

    🔒【预防措施 & 提醒】

    【⚠️ 注意】

    • 输入输出量大,务必加 ios::sync_with_stdio(false); cin.tie(nullptr);
    • 数值范围可达 10⁹,计算差值时注意 abs(right - x) 可能溢出 int,应转 long long
    • x 小于所有元素时,只有右侧有值;反之亦然

    📊 测试建议

    可构造以下测试用例验证:

    输入:
    5
    1 3 5 7 9
    4
    0   -> 应输出 1
    2   -> 应输出 1 或 3?距离都是1 → 输出 1(更小)
    6   -> 应输出 5  7 距离都是1 → 输出 5
    10  -> 应输出 9
    

    ✅ 最终通过策略总结

    要点建议
    算法二分查找(lower_bound)
    数据结构vector
    复杂度O(m log n)
    关键点比较前后两个候选值,距离相等取小值
    优化关闭同步流加速 IO

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 11月4日
  • 已采纳回答 10月27日
  • 创建了问题 10月27日