迷宫的寻宝游戏
题目理解
这道题目描述了一个"整数迷宫"的寻宝场景,我们需要解决的核心问题是:给定一组数字集合,然后快速判断多个查询数字是否存在于这个集合中。
输入要求:
- 
第一行两个整数N和M,分别表示数字集合的大小和查询次数 
- 
第二行包含N个整数的集合 
- 
接下来M行,每行一个查询数字d 
输出要求:
- 
对于每个查询数字d,如果存在于集合中输出"Yes",否则输出"No" 
解题思路
- 
数据规模分析:题目给出的N可以达到10^6,M可以达到10^4,这意味着我们需要一个高效的查找算法。 
- 
算法选择: - 
直接遍历查找:时间复杂度O(M*N),对于最大数据量会是10^10次操作,显然太慢 
- 
二分查找:先排序(O(N log N)),然后每次查询O(log N),总复杂度O(N log N + M log N),完全能够处理题目给出的数据规模 
 
- 
- 
实现步骤: - 
读取输入数据 
- 
对数字集合进行排序(为二分查找做准备) 
- 
对于每个查询数字,使用二分查找判断是否存在 
- 
输出结果 
 
- 
参考代码
#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的方式提高输入效率:
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号