迷宫的寻宝游戏

题目理解

这道题目描述了一个"整数迷宫"的寻宝场景,我们需要解决的核心问题是:给定一组数字集合,然后快速判断多个查询数字是否存在于这个集合中。

输入要求:

  • 第一行两个整数N和M,分别表示数字集合的大小和查询次数

  • 第二行包含N个整数的集合

  • 接下来M行,每行一个查询数字d

输出要求:

  • 对于每个查询数字d,如果存在于集合中输出"Yes",否则输出"No"

解题思路

  1. 数据规模分析:题目给出的N可以达到10^6,M可以达到10^4,这意味着我们需要一个高效的查找算法。

  2. 算法选择

    • 直接遍历查找:时间复杂度O(M*N),对于最大数据量会是10^10次操作,显然太慢

    • 二分查找:先排序(O(N log N)),然后每次查询O(log N),总复杂度O(N log N + M log N),完全能够处理题目给出的数据规模

  3. 实现步骤

    • 读取输入数据

    • 对数字集合进行排序(为二分查找做准备)

    • 对于每个查询数字,使用二分查找判断是否存在

    • 输出结果

参考代码

#include<bits/stdc++.h>
using namespace std;

const int N = 1e6 + 5; // 定义数组最大大小,比题目要求的1e6稍大一些
int a[N], n, m; // a数组存储数字集合,n是集合大小,m是查询次数

int main() {
    // 读取输入
    cin >> n >> m; // 读取数字集合大小n和查询次数m
    for (int i = 1; i <= n; i++) cin >> a[i]; // 读取n个数字到数组中

    // 对数组进行排序,为二分查找做准备
    // 注意这里排序范围是从a[1]到a[n],因为题目中数组是从1开始使用的
    sort(a+1, a+1+n);
    
    // 处理每个查询
    for (int i = 1; i <= m; i++) {
        int L = 1, R = n, target; // 初始化二分查找的左右边界
        bool f = false; // 标记是否找到目标
        cin >> target; // 读取当前要查询的数字
        
        // 二分查找过程
        while (L <= R) {
            int mid = (L + R) / 2; // 计算中间位置
            if (a[mid] == target) { // 如果找到目标
                f = true; // 设置标记为true
                break; // 退出循环
            } else if (a[mid] < target) { // 如果中间值小于目标
                L = mid + 1; // 调整左边界
            } else { // 如果中间值大于目标
                R = mid - 1; // 调整右边界
            }
        }
        
        // 输出结果
        if (f) cout << "Yes" << endl;
        else cout << "No" << endl;
    }

    return 0;
}

复杂度分析

  • 时间复杂度

    • 排序操作:O(N log N)

    • M次二分查找:O(M log N)

    • 总时间复杂度:O((N + M) log N)

  • 空间复杂度

    • O(N),用于存储数字集合

优化思考

如果数据范围进一步增加,可以在输入时使用scanf的方式提高输入效率:

posted @ 2025-05-07 15:27  行胜于言Ibl  阅读(22)  评论(0)    收藏  举报